home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume26 / cook-1.4 / part08 < prev    next >
Encoding:
Text File  |  1993-05-03  |  80.6 KB  |  3,198 lines

  1. Newsgroups: comp.sources.unix
  2. From: pmiller@bmr.gov.au (Peter Miller)
  3. Subject: v26i216: cook-1.4 - a file construction tool (like "make"), Part08/11
  4. Sender: unix-sources-moderator@efficacy.home.vix.com
  5. Approved: WhoAmI@efficacy.home.vix.com
  6.  
  7. Submitted-By: pmiller@bmr.gov.au (Peter Miller)
  8. Posting-Number: Volume 26, Issue 216
  9. Archive-Name: cook-1.4/part08
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 8 (of 11)."
  18. # Contents:  LICENSE common/str.c cook/main.c doc/language
  19. # Wrapped by vixie@efficacy.home.vix.com on Tue May  4 01:36:41 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'LICENSE' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'LICENSE'\"
  23. else
  24. echo shar: Extracting \"'LICENSE'\" \(17982 characters\)
  25. sed "s/^X//" >'LICENSE' <<'END_OF_FILE'
  26. X            GNU GENERAL PUBLIC LICENSE
  27. X               Version 2, June 1991
  28. X
  29. X Copyright (C) 1989, 1991 Free Software Foundation, Inc.
  30. X                          675 Mass Ave, Cambridge, MA 02139, USA
  31. X Everyone is permitted to copy and distribute verbatim copies
  32. X of this license document, but changing it is not allowed.
  33. X
  34. X                Preamble
  35. X
  36. X  The licenses for most software are designed to take away your
  37. Xfreedom to share and change it.  By contrast, the GNU General Public
  38. XLicense is intended to guarantee your freedom to share and change free
  39. Xsoftware--to make sure the software is free for all its users.  This
  40. XGeneral Public License applies to most of the Free Software
  41. XFoundation's software and to any other program whose authors commit to
  42. Xusing it.  (Some other Free Software Foundation software is covered by
  43. Xthe GNU Library General Public License instead.)  You can apply it to
  44. Xyour programs, too.
  45. X
  46. X  When we speak of free software, we are referring to freedom, not
  47. Xprice.  Our General Public Licenses are designed to make sure that you
  48. Xhave the freedom to distribute copies of free software (and charge for
  49. Xthis service if you wish), that you receive source code or can get it
  50. Xif you want it, that you can change the software or use pieces of it
  51. Xin new free programs; and that you know you can do these things.
  52. X
  53. X  To protect your rights, we need to make restrictions that forbid
  54. Xanyone to deny you these rights or to ask you to surrender the rights.
  55. XThese restrictions translate to certain responsibilities for you if you
  56. Xdistribute copies of the software, or if you modify it.
  57. X
  58. X  For example, if you distribute copies of such a program, whether
  59. Xgratis or for a fee, you must give the recipients all the rights that
  60. Xyou have.  You must make sure that they, too, receive or can get the
  61. Xsource code.  And you must show them these terms so they know their
  62. Xrights.
  63. X
  64. X  We protect your rights with two steps: (1) copyright the software, and
  65. X(2) offer you this license which gives you legal permission to copy,
  66. Xdistribute and/or modify the software.
  67. X
  68. X  Also, for each author's protection and ours, we want to make certain
  69. Xthat everyone understands that there is no warranty for this free
  70. Xsoftware.  If the software is modified by someone else and passed on, we
  71. Xwant its recipients to know that what they have is not the original, so
  72. Xthat any problems introduced by others will not reflect on the original
  73. Xauthors' reputations.
  74. X
  75. X  Finally, any free program is threatened constantly by software
  76. Xpatents.  We wish to avoid the danger that redistributors of a free
  77. Xprogram will individually obtain patent licenses, in effect making the
  78. Xprogram proprietary.  To prevent this, we have made it clear that any
  79. Xpatent must be licensed for everyone's free use or not licensed at all.
  80. X
  81. X  The precise terms and conditions for copying, distribution and
  82. Xmodification follow.
  83. X
  84. X            GNU GENERAL PUBLIC LICENSE
  85. X   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  86. X
  87. X  0. This License applies to any program or other work which contains
  88. Xa notice placed by the copyright holder saying it may be distributed
  89. Xunder the terms of this General Public License.  The "Program", below,
  90. Xrefers to any such program or work, and a "work based on the Program"
  91. Xmeans either the Program or any derivative work under copyright law:
  92. Xthat is to say, a work containing the Program or a portion of it,
  93. Xeither verbatim or with modifications and/or translated into another
  94. Xlanguage.  (Hereinafter, translation is included without limitation in
  95. Xthe term "modification".)  Each licensee is addressed as "you".
  96. X
  97. XActivities other than copying, distribution and modification are not
  98. Xcovered by this License; they are outside its scope.  The act of
  99. Xrunning the Program is not restricted, and the output from the Program
  100. Xis covered only if its contents constitute a work based on the
  101. XProgram (independent of having been made by running the Program).
  102. XWhether that is true depends on what the Program does.
  103. X
  104. X  1. You may copy and distribute verbatim copies of the Program's
  105. Xsource code as you receive it, in any medium, provided that you
  106. Xconspicuously and appropriately publish on each copy an appropriate
  107. Xcopyright notice and disclaimer of warranty; keep intact all the
  108. Xnotices that refer to this License and to the absence of any warranty;
  109. Xand give any other recipients of the Program a copy of this License
  110. Xalong with the Program.
  111. X
  112. XYou may charge a fee for the physical act of transferring a copy, and
  113. Xyou may at your option offer warranty protection in exchange for a fee.
  114. X
  115. X  2. You may modify your copy or copies of the Program or any portion
  116. Xof it, thus forming a work based on the Program, and copy and
  117. Xdistribute such modifications or work under the terms of Section 1
  118. Xabove, provided that you also meet all of these conditions:
  119. X
  120. X    a) You must cause the modified files to carry prominent notices
  121. X    stating that you changed the files and the date of any change.
  122. X
  123. X    b) You must cause any work that you distribute or publish, that in
  124. X    whole or in part contains or is derived from the Program or any
  125. X    part thereof, to be licensed as a whole at no charge to all third
  126. X    parties under the terms of this License.
  127. X
  128. X    c) If the modified program normally reads commands interactively
  129. X    when run, you must cause it, when started running for such
  130. X    interactive use in the most ordinary way, to print or display an
  131. X    announcement including an appropriate copyright notice and a
  132. X    notice that there is no warranty (or else, saying that you provide
  133. X    a warranty) and that users may redistribute the program under
  134. X    these conditions, and telling the user how to view a copy of this
  135. X    License.  (Exception: if the Program itself is interactive but
  136. X    does not normally print such an announcement, your work based on
  137. X    the Program is not required to print an announcement.)
  138. X
  139. XThese requirements apply to the modified work as a whole.  If
  140. Xidentifiable sections of that work are not derived from the Program,
  141. Xand can be reasonably considered independent and separate works in
  142. Xthemselves, then this License, and its terms, do not apply to those
  143. Xsections when you distribute them as separate works.  But when you
  144. Xdistribute the same sections as part of a whole which is a work based
  145. Xon the Program, the distribution of the whole must be on the terms of
  146. Xthis License, whose permissions for other licensees extend to the
  147. Xentire whole, and thus to each and every part regardless of who wrote it.
  148. X
  149. XThus, it is not the intent of this section to claim rights or contest
  150. Xyour rights to work written entirely by you; rather, the intent is to
  151. Xexercise the right to control the distribution of derivative or
  152. Xcollective works based on the Program.
  153. X
  154. XIn addition, mere aggregation of another work not based on the Program
  155. Xwith the Program (or with a work based on the Program) on a volume of
  156. Xa storage or distribution medium does not bring the other work under
  157. Xthe scope of this License.
  158. X
  159. X  3. You may copy and distribute the Program (or a work based on it,
  160. Xunder Section 2) in object code or executable form under the terms of
  161. XSections 1 and 2 above provided that you also do one of the following:
  162. X
  163. X    a) Accompany it with the complete corresponding machine-readable
  164. X    source code, which must be distributed under the terms of Sections
  165. X    1 and 2 above on a medium customarily used for software interchange; or,
  166. X
  167. X    b) Accompany it with a written offer, valid for at least three
  168. X    years, to give any third party, for a charge no more than your
  169. X    cost of physically performing source distribution, a complete
  170. X    machine-readable copy of the corresponding source code, to be
  171. X    distributed under the terms of Sections 1 and 2 above on a medium
  172. X    customarily used for software interchange; or,
  173. X
  174. X    c) Accompany it with the information you received as to the offer
  175. X    to distribute corresponding source code.  (This alternative is
  176. X    allowed only for noncommercial distribution and only if you
  177. X    received the program in object code or executable form with such
  178. X    an offer, in accord with Subsection b above.)
  179. X
  180. XThe source code for a work means the preferred form of the work for
  181. Xmaking modifications to it.  For an executable work, complete source
  182. Xcode means all the source code for all modules it contains, plus any
  183. Xassociated interface definition files, plus the scripts used to
  184. Xcontrol compilation and installation of the executable.  However, as a
  185. Xspecial exception, the source code distributed need not include
  186. Xanything that is normally distributed (in either source or binary
  187. Xform) with the major components (compiler, kernel, and so on) of the
  188. Xoperating system on which the executable runs, unless that component
  189. Xitself accompanies the executable.
  190. X
  191. XIf distribution of executable or object code is made by offering
  192. Xaccess to copy from a designated place, then offering equivalent
  193. Xaccess to copy the source code from the same place counts as
  194. Xdistribution of the source code, even though third parties are not
  195. Xcompelled to copy the source along with the object code.
  196. X
  197. X  4. You may not copy, modify, sublicense, or distribute the Program
  198. Xexcept as expressly provided under this License.  Any attempt
  199. Xotherwise to copy, modify, sublicense or distribute the Program is
  200. Xvoid, and will automatically terminate your rights under this License.
  201. XHowever, parties who have received copies, or rights, from you under
  202. Xthis License will not have their licenses terminated so long as such
  203. Xparties remain in full compliance.
  204. X
  205. X  5. You are not required to accept this License, since you have not
  206. Xsigned it.  However, nothing else grants you permission to modify or
  207. Xdistribute the Program or its derivative works.  These actions are
  208. Xprohibited by law if you do not accept this License.  Therefore, by
  209. Xmodifying or distributing the Program (or any work based on the
  210. XProgram), you indicate your acceptance of this License to do so, and
  211. Xall its terms and conditions for copying, distributing or modifying
  212. Xthe Program or works based on it.
  213. X
  214. X  6. Each time you redistribute the Program (or any work based on the
  215. XProgram), the recipient automatically receives a license from the
  216. Xoriginal licensor to copy, distribute or modify the Program subject to
  217. Xthese terms and conditions.  You may not impose any further
  218. Xrestrictions on the recipients' exercise of the rights granted herein.
  219. XYou are not responsible for enforcing compliance by third parties to
  220. Xthis License.
  221. X
  222. X  7. If, as a consequence of a court judgment or allegation of patent
  223. Xinfringement or for any other reason (not limited to patent issues),
  224. Xconditions are imposed on you (whether by court order, agreement or
  225. Xotherwise) that contradict the conditions of this License, they do not
  226. Xexcuse you from the conditions of this License.  If you cannot
  227. Xdistribute so as to satisfy simultaneously your obligations under this
  228. XLicense and any other pertinent obligations, then as a consequence you
  229. Xmay not distribute the Program at all.  For example, if a patent
  230. Xlicense would not permit royalty-free redistribution of the Program by
  231. Xall those who receive copies directly or indirectly through you, then
  232. Xthe only way you could satisfy both it and this License would be to
  233. Xrefrain entirely from distribution of the Program.
  234. X
  235. XIf any portion of this section is held invalid or unenforceable under
  236. Xany particular circumstance, the balance of the section is intended to
  237. Xapply and the section as a whole is intended to apply in other
  238. Xcircumstances.
  239. X
  240. XIt is not the purpose of this section to induce you to infringe any
  241. Xpatents or other property right claims or to contest validity of any
  242. Xsuch claims; this section has the sole purpose of protecting the
  243. Xintegrity of the free software distribution system, which is
  244. Ximplemented by public license practices.  Many people have made
  245. Xgenerous contributions to the wide range of software distributed
  246. Xthrough that system in reliance on consistent application of that
  247. Xsystem; it is up to the author/donor to decide if he or she is willing
  248. Xto distribute software through any other system and a licensee cannot
  249. Ximpose that choice.
  250. X
  251. XThis section is intended to make thoroughly clear what is believed to
  252. Xbe a consequence of the rest of this License.
  253. X
  254. X  8. If the distribution and/or use of the Program is restricted in
  255. Xcertain countries either by patents or by copyrighted interfaces, the
  256. Xoriginal copyright holder who places the Program under this License
  257. Xmay add an explicit geographical distribution limitation excluding
  258. Xthose countries, so that distribution is permitted only in or among
  259. Xcountries not thus excluded.  In such case, this License incorporates
  260. Xthe limitation as if written in the body of this License.
  261. X
  262. X  9. The Free Software Foundation may publish revised and/or new versions
  263. Xof the General Public License from time to time.  Such new versions will
  264. Xbe similar in spirit to the present version, but may differ in detail to
  265. Xaddress new problems or concerns.
  266. X
  267. XEach version is given a distinguishing version number.  If the Program
  268. Xspecifies a version number of this License which applies to it and "any
  269. Xlater version", you have the option of following the terms and conditions
  270. Xeither of that version or of any later version published by the Free
  271. XSoftware Foundation.  If the Program does not specify a version number of
  272. Xthis License, you may choose any version ever published by the Free Software
  273. XFoundation.
  274. X
  275. X  10. If you wish to incorporate parts of the Program into other free
  276. Xprograms whose distribution conditions are different, write to the author
  277. Xto ask for permission.  For software which is copyrighted by the Free
  278. XSoftware Foundation, write to the Free Software Foundation; we sometimes
  279. Xmake exceptions for this.  Our decision will be guided by the two goals
  280. Xof preserving the free status of all derivatives of our free software and
  281. Xof promoting the sharing and reuse of software generally.
  282. X
  283. X                NO WARRANTY
  284. X
  285. X  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
  286. XFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
  287. XOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
  288. XPROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
  289. XOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  290. XMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
  291. XTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
  292. XPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
  293. XREPAIR OR CORRECTION.
  294. X
  295. X  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  296. XWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
  297. XREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  298. XINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
  299. XOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
  300. XTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
  301. XYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
  302. XPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
  303. XPOSSIBILITY OF SUCH DAMAGES.
  304. X
  305. X             END OF TERMS AND CONDITIONS
  306. X
  307. X    Appendix: How to Apply These Terms to Your New Programs
  308. X
  309. X  If you develop a new program, and you want it to be of the greatest
  310. Xpossible use to the public, the best way to achieve this is to make it
  311. Xfree software which everyone can redistribute and change under these terms.
  312. X
  313. X  To do so, attach the following notices to the program.  It is safest
  314. Xto attach them to the start of each source file to most effectively
  315. Xconvey the exclusion of warranty; and each file should have at least
  316. Xthe "copyright" line and a pointer to where the full notice is found.
  317. X
  318. X    <one line to give the program's name and a brief idea of what it does.>
  319. X    Copyright (C) 19yy  <name of author>
  320. X
  321. X    This program is free software; you can redistribute it and/or modify
  322. X    it under the terms of the GNU General Public License as published by
  323. X    the Free Software Foundation; either version 2 of the License, or
  324. X    (at your option) any later version.
  325. X
  326. X    This program is distributed in the hope that it will be useful,
  327. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  328. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  329. X    GNU General Public License for more details.
  330. X
  331. X    You should have received a copy of the GNU General Public License
  332. X    along with this program; if not, write to the Free Software
  333. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  334. X
  335. XAlso add information on how to contact you by electronic and paper mail.
  336. X
  337. XIf the program is interactive, make it output a short notice like this
  338. Xwhen it starts in an interactive mode:
  339. X
  340. X    Gnomovision version 69, Copyright (C) 19yy name of author
  341. X    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
  342. X    This is free software, and you are welcome to redistribute it
  343. X    under certain conditions; type `show c' for details.
  344. X
  345. XThe hypothetical commands `show w' and `show c' should show the appropriate
  346. Xparts of the General Public License.  Of course, the commands you use may
  347. Xbe called something other than `show w' and `show c'; they could even be
  348. Xmouse-clicks or menu items--whatever suits your program.
  349. X
  350. XYou should also get your employer (if you work as a programmer) or your
  351. Xschool, if any, to sign a "copyright disclaimer" for the program, if
  352. Xnecessary.  Here is a sample; alter the names:
  353. X
  354. X  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  355. X  `Gnomovision' (which makes passes at compilers) written by James Hacker.
  356. X
  357. X  <signature of Ty Coon>, 1 April 1989
  358. X  Ty Coon, President of Vice
  359. X
  360. XThis General Public License does not permit incorporating your program into
  361. Xproprietary programs.  If your program is a subroutine library, you may
  362. Xconsider it more useful to permit linking proprietary applications with the
  363. Xlibrary.  If this is what you want to do, use the GNU Library General
  364. XPublic License instead of this License.
  365. END_OF_FILE
  366. if test 17982 -ne `wc -c <'LICENSE'`; then
  367.     echo shar: \"'LICENSE'\" unpacked with wrong size!
  368. fi
  369. # end of 'LICENSE'
  370. fi
  371. if test -f 'common/str.c' -a "${1}" != "-c" ; then 
  372.   echo shar: Will not clobber existing file \"'common/str.c'\"
  373. else
  374. echo shar: Extracting \"'common/str.c'\" \(22749 characters\)
  375. sed "s/^X//" >'common/str.c' <<'END_OF_FILE'
  376. X/*
  377. X *    cook - file construction tool
  378. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  379. X *    All rights reserved.
  380. X *
  381. X *    This program is free software; you can redistribute it and/or modify
  382. X *    it under the terms of the GNU General Public License as published by
  383. X *    the Free Software Foundation; either version 2 of the License, or
  384. X *    (at your option) any later version.
  385. X *
  386. X *    This program is distributed in the hope that it will be useful,
  387. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  388. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  389. X *    GNU General Public License for more details.
  390. X *
  391. X *    You should have received a copy of the GNU General Public License
  392. X *    along with this program; if not, write to the Free Software
  393. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  394. X *
  395. X * MANIFEST: functions to manipulate shared strings
  396. X *
  397. X * Strings are the most heavily used resource in cook.  They are manipulated
  398. X * inside the match functions, and hence are in the inside loop.  For this
  399. X * reason they must be fast.
  400. X *
  401. X * A literal pool is maintained.  Each string has a reference count.  The
  402. X * string stays in the literal pool for as long as it hash a positive
  403. X * reference count.  To determine if a string is already in the literal pool,
  404. X * linear dynamic hashing is used to guarantee an O(1) search.  That all equal
  405. X * strings are the same item in the literal pool means that string equality is
  406. X * a pointer test, and thus very fast.
  407. X */
  408. X
  409. X#include <ctype.h>
  410. X#include <stddef.h>
  411. X#include <stdio.h>
  412. X#include <stdlib.h>
  413. X#include <string.h>
  414. X
  415. X#include <error.h>
  416. X#include <mem.h>
  417. X#include <s-v-arg.h>
  418. X#include <str.h>
  419. X
  420. X
  421. X/*
  422. X * maximum conversion width for numbers
  423. X */
  424. X#define MAX_WIDTH 509
  425. X
  426. Xstring_ty *str_true;
  427. Xstring_ty *str_false;
  428. Xstatic string_ty **hash_table;
  429. Xstatic str_hash_ty hash_modulus;
  430. Xstatic str_hash_ty hash_cutover;
  431. Xstatic str_hash_ty hash_cutover_mask;
  432. Xstatic str_hash_ty hash_cutover_split_mask;
  433. Xstatic str_hash_ty hash_split;
  434. Xstatic str_hash_ty hash_load;
  435. X
  436. X#define MAX_HASH_LEN 20
  437. X
  438. X
  439. X/*
  440. X * NAME
  441. X *    hash_generate - hash string to number
  442. X *
  443. X * SYNOPSIS
  444. X *    str_hash_ty hash_generate(char *s, size_t n);
  445. X *
  446. X * DESCRIPTION
  447. X *    The hash_generate function is used to make a number from a string.
  448. X *
  449. X * RETURNS
  450. X *    str_hash_ty - the magic number
  451. X *
  452. X * CAVEAT
  453. X *    Only the last MAX_HASH_LEN characters are used.
  454. X *    It is important that str_hash_ty be unsigned (int or long).
  455. X */
  456. X
  457. Xstatic str_hash_ty hash_generate _((char *, size_t));
  458. X
  459. Xstatic str_hash_ty
  460. Xhash_generate(s, n)
  461. X    char        *s;
  462. X    size_t        n;
  463. X{
  464. X    str_hash_ty    retval;
  465. X
  466. X    if (n > MAX_HASH_LEN)
  467. X    {
  468. X        s += n - MAX_HASH_LEN;
  469. X        n = MAX_HASH_LEN;
  470. X    }
  471. X
  472. X    retval = 0;
  473. X    while (n > 0)
  474. X    {
  475. X        retval = (retval + (retval << 1)) ^ *s++;
  476. X        --n;
  477. X    }
  478. X    return retval;
  479. X}
  480. X
  481. X
  482. X/*
  483. X * NAME
  484. X *    str_valid - test a string
  485. X *
  486. X * SYNOPSIS
  487. X *    int str_valid(string_ty *s);
  488. X *
  489. X * DESCRIPTION
  490. X *    The str_valid function is used to test if a pointer points to a valid
  491. X *    string.
  492. X *
  493. X * RETURNS
  494. X *    int: zero if the string is not valid, nonzero if the string is valid.
  495. X *
  496. X * CAVEAT
  497. X *    This function is only available then the DEBUG symbol is #define'd.
  498. X */
  499. X
  500. X#ifdef DEBUG
  501. X
  502. Xint
  503. Xstr_valid(s)
  504. X    string_ty    *s;
  505. X{
  506. X    return
  507. X    (
  508. X        s->str_references > 0
  509. X    &&
  510. X        strlen(s->str_text) == s->str_length
  511. X    &&
  512. X        s->str_hash == hash_generate(s->str_text, s->str_length)
  513. X    );
  514. X}
  515. X
  516. X#endif
  517. X
  518. X
  519. X/*
  520. X * NAME
  521. X *    str_initialize - start up string table
  522. X *
  523. X * SYNOPSIS
  524. X *    void str_initialize(void);
  525. X *
  526. X * DESCRIPTION
  527. X *    The str_initialize function is used to create the hash table and
  528. X *    initialize it to empty.
  529. X *
  530. X * RETURNS
  531. X *    void
  532. X *
  533. X * CAVEAT
  534. X *    This function must be called before any other defined in this file.
  535. X */
  536. X
  537. Xvoid
  538. Xstr_initialize()
  539. X{
  540. X    str_hash_ty    j;
  541. X
  542. X    hash_modulus = 1 << 8; /* MUST be a power of 2 */
  543. X    hash_cutover = hash_modulus;
  544. X    hash_split = hash_modulus - hash_cutover;
  545. X    hash_cutover_mask = hash_cutover - 1;
  546. X    hash_cutover_split_mask = (hash_cutover * 2) - 1;
  547. X    hash_load = 0;
  548. X    hash_table = (string_ty **)mem_alloc(hash_modulus * sizeof(string_ty *));
  549. X    for (j = 0; j < hash_modulus; ++j)
  550. X        hash_table[j] = 0;
  551. X
  552. X    str_true = str_from_c("1");
  553. X    str_false = str_from_c("");
  554. X}
  555. X
  556. X
  557. X/*
  558. X * NAME
  559. X *    split - reduce table loading
  560. X *
  561. X * SYNOPSIS
  562. X *    void split(void);
  563. X *
  564. X * DESCRIPTION
  565. X *    The split function is used to reduce the load factor on the hash table.
  566. X *
  567. X * RETURNS
  568. X *    void
  569. X *
  570. X * CAVEAT
  571. X *    A load factor of about 80% is suggested.
  572. X */
  573. X
  574. Xstatic void split _((void));
  575. X
  576. Xstatic void
  577. Xsplit()
  578. X{
  579. X    string_ty    *p;
  580. X    string_ty    *p2;
  581. X    str_hash_ty    index;
  582. X
  583. X    /*
  584. X     * get the list to be split across buckets 
  585. X     */
  586. X    p = hash_table[hash_split];
  587. X    hash_table[hash_split] = 0;
  588. X
  589. X    /*
  590. X     * increase the modulus by one
  591. X     */
  592. X    hash_modulus++;
  593. X    mem_change_size
  594. X    (
  595. X        (char **)&hash_table,
  596. X        hash_modulus * sizeof(string_ty *)
  597. X    );
  598. X    hash_table[hash_modulus - 1] = 0;
  599. X    hash_split = hash_modulus - hash_cutover;
  600. X    if (hash_split >= hash_cutover)
  601. X    {
  602. X        hash_cutover = hash_modulus;
  603. X        hash_split = 0;
  604. X        hash_cutover_mask = hash_cutover - 1;
  605. X        hash_cutover_split_mask = (hash_cutover * 2) - 1;
  606. X    }
  607. X
  608. X    /*
  609. X     * now redistribute the list elements
  610. X     */
  611. X    while (p)
  612. X    {
  613. X        p2 = p;
  614. X        p = p->str_next;
  615. X
  616. X        index = p2->str_hash & hash_cutover_mask;
  617. X        if (index < hash_split)
  618. X            index = p2->str_hash & hash_cutover_split_mask;
  619. X        assert(index < hash_modulus);
  620. X        p2->str_next = hash_table[index];
  621. X        hash_table[index] = p2;
  622. X    }
  623. X}
  624. X
  625. X
  626. X/*
  627. X * NAME
  628. X *    str_from_c - make string from C string
  629. X *
  630. X * SYNOPSIS
  631. X *    string_ty *str_from_c(char*);
  632. X *
  633. X * DESCRIPTION
  634. X *    The str_from_c function is used to make a string from a null terminated
  635. X *    C string.
  636. X *
  637. X * RETURNS
  638. X *    string_ty * - a pointer to a string in dynamic memory.  Use str_free when
  639. X *    finished with.
  640. X *
  641. X * CAVEAT
  642. X *    The contents of the structure pointed to MUST NOT be altered.
  643. X */
  644. X
  645. Xstring_ty *
  646. Xstr_from_c(s)
  647. X    char        *s;
  648. X{
  649. X    return str_n_from_c(s, strlen(s));
  650. X}
  651. X
  652. X
  653. X/*
  654. X * NAME
  655. X *    str_n_from_c - make string
  656. X *
  657. X * SYNOPSIS
  658. X *    string_ty *str_n_from_c(char *s, size_t n);
  659. X *
  660. X * DESCRIPTION
  661. X *    The str_n_from_c function is used to make a string from an array of
  662. X *    characters.  No null terminator is assumed.
  663. X *
  664. X * RETURNS
  665. X *    string_ty * - a pointer to a string in dynamic memory.  Use str_free when
  666. X *    finished with.
  667. X *
  668. X * CAVEAT
  669. X *    The contents of the structure pointed to MUST NOT be altered.
  670. X */
  671. X
  672. Xstring_ty *
  673. Xstr_n_from_c(s, length)
  674. X    char        *s;
  675. X    size_t        length;
  676. X{
  677. X    str_hash_ty    hash;
  678. X    str_hash_ty    index;
  679. X    string_ty    *p;
  680. X
  681. X    hash = hash_generate(s, length);
  682. X
  683. X#ifdef DEBUG
  684. X    if (!hash_table)
  685. X        fatal("you must call str_initialize early in main()");
  686. X#endif
  687. X    index = hash & hash_cutover_mask;
  688. X    if (index < hash_split)
  689. X        index = hash & hash_cutover_split_mask;
  690. X    assert(index < hash_modulus);
  691. X
  692. X    for (p = hash_table[index]; p; p = p->str_next)
  693. X    {
  694. X        if
  695. X        (
  696. X            p->str_hash == hash
  697. X        &&
  698. X            p->str_length == length
  699. X        &&
  700. X            !memcmp(p->str_text, s, length)
  701. X        )
  702. X        {
  703. X            p->str_references++;
  704. X            return p;
  705. X        }
  706. X    }
  707. X
  708. X    p = (string_ty *)mem_alloc(sizeof(string_ty) + length);
  709. X    p->str_hash = hash;
  710. X    p->str_length = length;
  711. X    p->str_references = 1;
  712. X    p->str_next = hash_table[index];
  713. X    hash_table[index] = p;
  714. X    memcpy(p->str_text, s, length);
  715. X    p->str_text[length] = 0;
  716. X
  717. X    hash_load++;
  718. X    while (hash_load * 10 > hash_modulus * 8)
  719. X        split();
  720. X    return p;
  721. X}
  722. X
  723. X
  724. X/*
  725. X * NAME
  726. X *    str_copy - make a copy of a string
  727. X *
  728. X * SYNOPSIS
  729. X *    string_ty *str_copy(string_ty *s);
  730. X *
  731. X * DESCRIPTION
  732. X *    The str_copy function is used to make a copy of a string.
  733. X *
  734. X * RETURNS
  735. X *    string_ty * - a pointer to a string in dynamic memory.  Use str_free when
  736. X *    finished with.
  737. X *
  738. X * CAVEAT
  739. X *    The contents of the structure pointed to MUST NOT be altered.
  740. X */
  741. X
  742. Xstring_ty *
  743. Xstr_copy(s)
  744. X    string_ty    *s;
  745. X{
  746. X    s->str_references++;
  747. X    return s;
  748. X}
  749. X
  750. X
  751. X/*
  752. X * NAME
  753. X *    str_free - release a string
  754. X *
  755. X * SYNOPSIS
  756. X *    void str_free(string_ty *s);
  757. X *
  758. X * DESCRIPTION
  759. X *    The str_free function is used to indicate that a string hash been
  760. X *    finished with.
  761. X *
  762. X * RETURNS
  763. X *    void
  764. X *
  765. X * CAVEAT
  766. X *    This is the only way to release strings DO NOT use the free function.
  767. X */
  768. X
  769. Xvoid
  770. Xstr_free(s)
  771. X    string_ty    *s;
  772. X{
  773. X    str_hash_ty    index;
  774. X    string_ty    **spp;
  775. X
  776. X    assert(str_valid(s));
  777. X    if (s->str_references > 1)
  778. X    {
  779. X        s->str_references--;
  780. X        return;
  781. X    }
  782. X    assert(s->str_references == 1);
  783. X
  784. X    /*
  785. X     *  find the hash bucket it was in,
  786. X     *  and remove it
  787. X     */
  788. X    index = s->str_hash & hash_cutover_mask;
  789. X    if (index < hash_split)
  790. X        index = s->str_hash & hash_cutover_split_mask;
  791. X    assert(index < hash_modulus);
  792. X    for (spp = &hash_table[index]; *spp; spp = &(*spp)->str_next)
  793. X    {
  794. X        if (*spp == s)
  795. X        {
  796. X            *spp = s->str_next;
  797. X            free(s);
  798. X            --hash_load;
  799. X            return;
  800. X        }
  801. X    }
  802. X    /* should never reach here! */
  803. X    fatal("attempted to free non-existent string (bug)");
  804. X}
  805. X
  806. X
  807. X/*
  808. X * NAME
  809. X *    str_catenate - join two strings
  810. X *
  811. X * SYNOPSIS
  812. X *    string_ty *str_catenate(string_ty *, string_ty *);
  813. X *
  814. X * DESCRIPTION
  815. X *    The str_catenate function is used to concatenate two strings to form a
  816. X *    new string.
  817. X *
  818. X * RETURNS
  819. X *    string_ty * - a pointer to a string in dynamic memory.  Use str_free when
  820. X *    finished with.
  821. X *
  822. X * CAVEAT
  823. X *    The contents of the structure pointed to MUST NOT be altered.
  824. X */
  825. X
  826. Xstring_ty *
  827. Xstr_catenate(s1, s2)
  828. X    string_ty    *s1;
  829. X    string_ty    *s2;
  830. X{
  831. X    static char    *tmp;
  832. X    static size_t    tmplen;
  833. X    string_ty    *s;
  834. X    size_t        length;
  835. X
  836. X    length = s1->str_length + s2->str_length;
  837. X    if (!tmp)
  838. X    {
  839. X        tmplen = length;
  840. X        if (tmplen < 16)
  841. X            tmplen = 16;
  842. X        tmp = mem_alloc(tmplen);
  843. X    }
  844. X    else
  845. X    {
  846. X        if (tmplen < length)
  847. X        {
  848. X            tmplen = length;
  849. X            mem_change_size(&tmp, tmplen);
  850. X        }
  851. X    }
  852. X    memcpy(tmp, s1->str_text, s1->str_length);
  853. X    memcpy(tmp + s1->str_length, s2->str_text, s2->str_length);
  854. X    s = str_n_from_c(tmp, length); 
  855. X    return s;
  856. X}
  857. X
  858. X
  859. X/*
  860. X * NAME
  861. X *    str_cat_three - join three strings
  862. X *
  863. X * SYNOPSIS
  864. X *    string_ty *str_cat_three(string_ty *, string_ty *, string_ty *);
  865. X *
  866. X * DESCRIPTION
  867. X *    The str_cat_three function is used to concatenate three strings to form
  868. X *    a new string.
  869. X *
  870. X * RETURNS
  871. X *    string_ty * - a pointer to a string in dynamic memory.  Use str_free when
  872. X *    finished with.
  873. X *
  874. X * CAVEAT
  875. X *    The contents of the structure pointed to MUST NOT be altered.
  876. X */
  877. X
  878. Xstring_ty *
  879. Xstr_cat_three(s1, s2, s3)
  880. X    string_ty    *s1;
  881. X    string_ty    *s2;
  882. X    string_ty    *s3;
  883. X{
  884. X    static char    *tmp;
  885. X    static size_t    tmplen;
  886. X    string_ty    *s;
  887. X    size_t        length;
  888. X
  889. X    length = s1->str_length + s2->str_length + s3->str_length;
  890. X    if (!tmp)
  891. X    {
  892. X        tmplen = length;
  893. X        if (tmplen < 16)
  894. X            tmplen = 16;
  895. X        tmp = mem_alloc(tmplen);
  896. X    }
  897. X    else
  898. X    {
  899. X        if (tmplen < length)
  900. X        {
  901. X            tmplen = length;
  902. X            mem_change_size(&tmp, tmplen);
  903. X        }
  904. X    }
  905. X    memcpy(tmp, s1->str_text, s1->str_length);
  906. X    memcpy(tmp + s1->str_length, s2->str_text, s2->str_length);
  907. X    memcpy
  908. X    (
  909. X        tmp + s1->str_length + s2->str_length,
  910. X        s3->str_text,
  911. X        s3->str_length
  912. X    );
  913. X    s = str_n_from_c(tmp, length); 
  914. X    return s;
  915. X}
  916. X
  917. X
  918. X/*
  919. X * NAME
  920. X *    str_equal - test equality of strings
  921. X *
  922. X * SYNOPSIS
  923. X *    int str_equal(string_ty *, string_ty *);
  924. X *
  925. X * DESCRIPTION
  926. X *    The str_equal function is used to test if two strings are equal.
  927. X *
  928. X * RETURNS
  929. X *    int; zero if the strings are not equal, nonzero if the strings are
  930. X *    equal.
  931. X *
  932. X * CAVEAT
  933. X *    This function is implemented as a macro in strings.h
  934. X */
  935. X
  936. X#ifndef str_equal
  937. X
  938. Xint
  939. Xstr_equal(s1, s2)
  940. X    string_ty    *s1;
  941. X    string_ty    *s2;
  942. X{
  943. X    return (s1 == s2);
  944. X}
  945. X
  946. X#endif
  947. X
  948. X
  949. X/*
  950. X * NAME
  951. X *    str_upcase - upcase a string
  952. X *
  953. X * SYNOPSIS
  954. X *    string_ty *str_upcase(string_ty *);
  955. X *
  956. X * DESCRIPTION
  957. X *    The str_upcase function is used to form a string which is an upper case 
  958. X *    form of the supplied string.
  959. X *
  960. X * RETURNS
  961. X *    string_ty * - a pointer to a string in dynamic memory.  Use str_free when
  962. X *    finished with.
  963. X *
  964. X * CAVEAT
  965. X *    The contents of the structure pointed to MUST NOT be altered.
  966. X */
  967. X
  968. Xstring_ty *
  969. Xstr_upcase(s)
  970. X    string_ty    *s;
  971. X{
  972. X    static char    *tmp;
  973. X    static size_t    tmplen;
  974. X    string_ty    *retval;
  975. X    char        *cp1;
  976. X    char        *cp2;
  977. X
  978. X    if (!tmp)
  979. X    {
  980. X        tmplen = s->str_length;
  981. X        if (tmplen < 16)
  982. X            tmplen = 16;
  983. X        tmp = mem_alloc(tmplen);
  984. X    }
  985. X    else
  986. X    {
  987. X        if (tmplen < s->str_length)
  988. X        {
  989. X            tmplen = s->str_length;
  990. X            mem_change_size(&tmp, tmplen);
  991. X        }
  992. X    }
  993. X    for (cp1 = s->str_text, cp2 = tmp; *cp1; ++cp1, ++cp2)
  994. X    {
  995. X        int    c;
  996. X
  997. X        c = *cp1;
  998. X        if (c >= 'a' && c <= 'z')
  999. X            c += 'A' - 'a';
  1000. X        *cp2 = c;
  1001. X    }
  1002. X    retval = str_n_from_c(tmp, s->str_length);
  1003. X    return retval;
  1004. X}
  1005. X
  1006. X
  1007. X/*
  1008. X * NAME
  1009. X *    str_downcase - lowercase string
  1010. X *
  1011. X * SYNOPSIS
  1012. X *    string_ty *str_downcase(string_ty *);
  1013. X *
  1014. X * DESCRIPTION
  1015. X *    The str_downcase function is used to form a string which is a lowercase
  1016. X *    form of the supplied string.
  1017. X *
  1018. X * RETURNS
  1019. X *    string_ty * - a pointer to a string in dynamic memory.  Use str_free when
  1020. X *    finished with.
  1021. X *
  1022. X * CAVEAT
  1023. X *    The contents of the structure pointed to MUST NOT be altered.
  1024. X */
  1025. X
  1026. Xstring_ty *
  1027. Xstr_downcase(s)
  1028. X    string_ty    *s;
  1029. X{
  1030. X    static char    *tmp;
  1031. X    static size_t    tmplen;
  1032. X    string_ty    *retval;
  1033. X    char        *cp1;
  1034. X    char        *cp2;
  1035. X
  1036. X    if (!tmp)
  1037. X    {
  1038. X        tmplen = s->str_length;
  1039. X        if (tmplen < 16)
  1040. X            tmplen = 16;
  1041. X        tmp = mem_alloc(tmplen);
  1042. X    }
  1043. X    else
  1044. X    {
  1045. X        if (tmplen < s->str_length)
  1046. X        {
  1047. X            tmplen = s->str_length;
  1048. X            mem_change_size(&tmp, tmplen);
  1049. X        }
  1050. X    }
  1051. X    for (cp1 = s->str_text, cp2 = tmp; *cp1; ++cp1, ++cp2)
  1052. X    {
  1053. X        int c;
  1054. X
  1055. X        c = *cp1;
  1056. X        if (c >= 'A' && c <= 'Z')
  1057. X            c += 'a' - 'A';
  1058. X        *cp2 = c;
  1059. X    }
  1060. X    retval = str_n_from_c(tmp, s->str_length);
  1061. X    return retval;
  1062. X}
  1063. X
  1064. X
  1065. X/*
  1066. X * NAME
  1067. X *    str_bool - get boolean value
  1068. X *
  1069. X * SYNOPSIS
  1070. X *    int str_bool(string_ty *s);
  1071. X *
  1072. X * DESCRIPTION
  1073. X *    The str_bool function is used to determine the boolean value of the
  1074. X *    given string.  A "false" result is if the string is empty or
  1075. X *    0 or blank, and "true" otherwise.
  1076. X *
  1077. X * RETURNS
  1078. X *    int: zero to indicate a "false" result, nonzero to indicate a "true"
  1079. X *    result.
  1080. X */
  1081. X
  1082. Xint
  1083. Xstr_bool(s)
  1084. X    string_ty    *s;
  1085. X{
  1086. X    char        *cp;
  1087. X
  1088. X    cp = s->str_text;
  1089. X    while (*cp)
  1090. X    {
  1091. X        if (*cp != ' ' && *cp != '0')
  1092. X            return 1;
  1093. X        ++cp;
  1094. X    }
  1095. X    return 0;
  1096. X}
  1097. X
  1098. X
  1099. X/*
  1100. X * NAME
  1101. X *    str_field - extract a field from a string
  1102. X *
  1103. X * SYNOPSIS
  1104. X *    string_ty *str_field(string_ty *, char separator, int field_number);
  1105. X *
  1106. X * DESCRIPTION
  1107. X *    The str_field functipon is used to erxtract a field from a string.
  1108. X *    Fields of the string are separated by ``separator'' characters.
  1109. X *    Fields are numbered from 0.
  1110. X *
  1111. X * RETURNS
  1112. X *    Asking for a field off the end of the string will result in a null
  1113. X *    pointer return.  The null string is considered to have one empty field.
  1114. X */
  1115. X
  1116. Xstring_ty *
  1117. Xstr_field(s, sep, fldnum)
  1118. X    string_ty    *s;
  1119. X    int        sep;
  1120. X    int        fldnum;
  1121. X{
  1122. X    char        *cp;
  1123. X    char        *ep;
  1124. X
  1125. X    cp = s->str_text;
  1126. X    while (fldnum > 0)
  1127. X    {
  1128. X        ep = strchr(cp, sep);
  1129. X        if (!ep)
  1130. X            return 0;
  1131. X        cp = ep + 1;
  1132. X        --fldnum;
  1133. X    }
  1134. X    ep = strchr(cp, sep);
  1135. X    if (ep)
  1136. X        return str_n_from_c(cp, ep - cp);
  1137. X    return str_from_c(cp);
  1138. X}
  1139. X
  1140. X
  1141. X/*
  1142. X * NAME
  1143. X *    str_format - analog of sprintf
  1144. X *
  1145. X * SYNOPSIS
  1146. X *    string_ty *str_format(char *, ...);
  1147. X *
  1148. X * DESCRIPTION
  1149. X *    The str_format function is used to create new strings
  1150. X *    using a format specification similar to printf(3).
  1151. X *    The "%S" specifier is used to mean a ``string_ty *'' string.
  1152. X *
  1153. X * RETURNS
  1154. X *    string_ty * - a pointer to a string in dynamic memory.  Use str_free when
  1155. X *    finished with.
  1156. X */
  1157. X
  1158. X
  1159. Xstring_ty *
  1160. Xstr_format(fmt sva_last)
  1161. X    char        *fmt;
  1162. X    sva_last_decl
  1163. X{
  1164. X    va_list        ap;
  1165. X    string_ty    *result;
  1166. X
  1167. X    sva_init(ap, fmt);
  1168. X    result = str_vformat(fmt, ap);
  1169. X    va_end(ap);
  1170. X    return result;
  1171. X}
  1172. X
  1173. X
  1174. Xstatic void build_fake _((char *fake, int flag, int width, int precision,
  1175. X    int qualifier, int specifier));
  1176. X
  1177. Xstatic void
  1178. Xbuild_fake(fake, flag, width, precision, qualifier, specifier)
  1179. X    char        *fake;
  1180. X    int        flag;
  1181. X    int        width;
  1182. X    int        precision;
  1183. X    int        qualifier;
  1184. X    int        specifier;
  1185. X{
  1186. X    char        *fp;
  1187. X
  1188. X    fp = fake;
  1189. X    *fp++ = '%';
  1190. X    if (flag)
  1191. X        *fp++ = flag;
  1192. X    if (width > 0)
  1193. X    {
  1194. X        sprintf(fp, "%d", width);
  1195. X        fp += strlen(fp);
  1196. X    }
  1197. X    *fp++ = '.';
  1198. X    sprintf(fp, "%d", precision);
  1199. X    fp += strlen(fp);
  1200. X    if (qualifier)
  1201. X        *fp++ = qualifier;
  1202. X    *fp++ = specifier;
  1203. X    *fp = 0;
  1204. X}
  1205. X
  1206. X
  1207. Xstring_ty *
  1208. Xstr_vformat(fmt, ap)
  1209. X    char        *fmt;
  1210. X    va_list        ap;
  1211. X{
  1212. X    size_t        length;
  1213. X    static size_t    tmplen;
  1214. X    static char    *tmp;
  1215. X    int        width;
  1216. X    int        width_set;
  1217. X    int        prec;
  1218. X    int        prec_set;
  1219. X    int        c;
  1220. X    char        *s;
  1221. X    int        qualifier;
  1222. X    int        flag;
  1223. X    char        fake[100];
  1224. X
  1225. X    /*
  1226. X     * Build the result string in a temporary buffer.
  1227. X     * Grow the temporary buffer as necessary.
  1228. X     *
  1229. X     * It is important to only make one pass across the variable argument
  1230. X     * list.  Behaviour is undefined for more than one pass.
  1231. X     */
  1232. X    if (!tmplen)
  1233. X    {
  1234. X        tmplen = 500;
  1235. X        tmp = mem_alloc(tmplen);
  1236. X    }
  1237. X    length = 0;
  1238. X    s = fmt;
  1239. X    while (*s)
  1240. X    {
  1241. X        c = *s++;
  1242. X        if (c != '%')
  1243. X        {
  1244. X            normal:
  1245. X            if (length >= tmplen)
  1246. X            {
  1247. X                tmplen += 100;
  1248. X                mem_change_size(&tmp, tmplen);
  1249. X            }
  1250. X            tmp[length++] = c;
  1251. X            continue;
  1252. X        }
  1253. X        c = *s++;
  1254. X
  1255. X        /*
  1256. X         * get optional flag
  1257. X         */
  1258. X        switch (c)
  1259. X        {
  1260. X        case '+':
  1261. X        case '-':
  1262. X        case '#':
  1263. X        case '0':
  1264. X        case ' ':
  1265. X            flag = c;
  1266. X            c = *s++;
  1267. X            break;
  1268. X
  1269. X        default:
  1270. X            flag = 0;
  1271. X            break;
  1272. X        }
  1273. X
  1274. X        /*
  1275. X         * get optional width
  1276. X         */
  1277. X        width = 0;
  1278. X        width_set = 0;
  1279. X        switch (c)
  1280. X        {
  1281. X        case '*':
  1282. X            width = va_arg(ap, int);
  1283. X            if (width < 0)
  1284. X            {
  1285. X                flag = '-';
  1286. X                width = -width;
  1287. X            }
  1288. X            c = *s++;
  1289. X            width_set = 1;
  1290. X            break;
  1291. X        
  1292. X        case '0': case '1': case '2': case '3': case '4':
  1293. X        case '5': case '6': case '7': case '8': case '9':
  1294. X            for (;;)
  1295. X            {
  1296. X                width = width * 10 + c - '0';
  1297. X                c = *s++;
  1298. X                switch (c)
  1299. X                {
  1300. X                default:
  1301. X                    break;
  1302. X
  1303. X                case '0': case '1': case '2': case '3':
  1304. X                case '4': case '5': case '6': case '7':
  1305. X                case '8': case '9':
  1306. X                    continue;
  1307. X                }
  1308. X                break;
  1309. X            }
  1310. X            width_set = 1;
  1311. X            break;
  1312. X
  1313. X        default:
  1314. X            break;
  1315. X        }
  1316. X
  1317. X        /*
  1318. X         * get optional precision
  1319. X         */
  1320. X        prec = 0;
  1321. X        prec_set = 0;
  1322. X        if (c == '.')
  1323. X        {
  1324. X            c = *s++;
  1325. X            switch (c)
  1326. X            {
  1327. X            default:
  1328. X                prec_set = 1;
  1329. X                break;
  1330. X
  1331. X            case '*':
  1332. X                c = *s++;
  1333. X                prec = va_arg(ap, int);
  1334. X                if (prec < 0)
  1335. X                {
  1336. X                    prec = 0;
  1337. X                    break;
  1338. X                }
  1339. X                prec_set = 1;
  1340. X                break;
  1341. X
  1342. X            case '0': case '1': case '2': case '3': case '4':
  1343. X            case '5': case '6': case '7': case '8': case '9':
  1344. X                for (;;)
  1345. X                {
  1346. X                    prec = prec * 10 + c - '0';
  1347. X                    c = *s++;
  1348. X                    switch (c)
  1349. X                    {
  1350. X                    default:
  1351. X                        break;
  1352. X
  1353. X                    case '0': case '1': case '2': case '3':
  1354. X                    case '4': case '5': case '6': case '7':
  1355. X                    case '8': case '9':
  1356. X                        continue;
  1357. X                    }
  1358. X                    break;
  1359. X                }
  1360. X                prec_set = 1;
  1361. X                break;
  1362. X            }
  1363. X        }
  1364. X
  1365. X        /*
  1366. X         * get the optional qualifier
  1367. X         */
  1368. X        switch (c)
  1369. X        {
  1370. X        default:
  1371. X            qualifier = 0;
  1372. X            break;
  1373. X
  1374. X        case 'l':
  1375. X        case 'h':
  1376. X        case 'L':
  1377. X            qualifier = c;
  1378. X            c = *s++;
  1379. X            break;
  1380. X        }
  1381. X
  1382. X        /*
  1383. X         * get conversion specifier
  1384. X         */
  1385. X        switch (c)
  1386. X        {
  1387. X        default:
  1388. X            fatal
  1389. X            (
  1390. X                  "in format string \"%s\", illegal specifier '%c'",
  1391. X                fmt,
  1392. X                c
  1393. X            );
  1394. X
  1395. X        case '%':
  1396. X            goto normal;
  1397. X
  1398. X        case 'c':
  1399. X            {
  1400. X                int    a;
  1401. X                char    num[MAX_WIDTH + 1];
  1402. X                size_t    len;
  1403. X
  1404. X                a = (unsigned char)va_arg(ap, int);
  1405. X                if (!prec_set)
  1406. X                    prec = 1;
  1407. X                if (width > MAX_WIDTH)
  1408. X                    width = MAX_WIDTH;
  1409. X                if (prec > MAX_WIDTH)
  1410. X                    prec = MAX_WIDTH;
  1411. X                build_fake(fake, flag, width, prec, 0, c);
  1412. X                sprintf(num, fake, a);
  1413. X                len = strlen(num);
  1414. X                if (length + len > tmplen)
  1415. X                {
  1416. X                    tmplen += len;
  1417. X                    mem_change_size(&tmp, tmplen);
  1418. X                }
  1419. X                memcpy(tmp + length, num, len);
  1420. X                length += len;
  1421. X            }
  1422. X            break;
  1423. X
  1424. X        case 'd':
  1425. X        case 'i':
  1426. X            {
  1427. X                long    a;
  1428. X                char    num[MAX_WIDTH + 1];
  1429. X                size_t    len;
  1430. X
  1431. X                switch (qualifier)
  1432. X                {
  1433. X                case 'l':
  1434. X                    a = va_arg(ap, long);
  1435. X                    break;
  1436. X
  1437. X                case 'h':
  1438. X                    a = (short)va_arg(ap, int);
  1439. X                    break;
  1440. X
  1441. X                default:
  1442. X                    a = va_arg(ap, int);
  1443. X                    break;
  1444. X                }
  1445. X                if (!prec_set)
  1446. X                    prec = 1;
  1447. X                if (width > MAX_WIDTH)
  1448. X                    width = MAX_WIDTH;
  1449. X                if (prec > MAX_WIDTH)
  1450. X                    prec = MAX_WIDTH;
  1451. X                build_fake(fake, flag, width, prec, 'l', c);
  1452. X                sprintf(num, fake, a);
  1453. X                len = strlen(num);
  1454. X                if (length + len > tmplen)
  1455. X                {
  1456. X                    tmplen += len;
  1457. X                    mem_change_size(&tmp, tmplen);
  1458. X                }
  1459. X                memcpy(tmp + length, num, len);
  1460. X                length += len;
  1461. X            }
  1462. X            break;
  1463. X
  1464. X        case 'e':
  1465. X        case 'f':
  1466. X        case 'g':
  1467. X        case 'E':
  1468. X        case 'F':
  1469. X        case 'G':
  1470. X            {
  1471. X                double    a;
  1472. X                char    num[MAX_WIDTH + 1];
  1473. X                size_t    len;
  1474. X
  1475. X                /*
  1476. X                 * Ignore "long double" for now,
  1477. X                 * traditional implementations no grok.
  1478. X                 */
  1479. X                a = va_arg(ap, double);
  1480. X                if (!prec_set)
  1481. X                    prec = 6;
  1482. X                if (width > MAX_WIDTH)
  1483. X                    width = MAX_WIDTH;
  1484. X                if (prec > MAX_WIDTH)
  1485. X                    prec = MAX_WIDTH;
  1486. X                build_fake(fake, flag, width, prec, 0, c);
  1487. X                sprintf(num, fake, a);
  1488. X                len = strlen(num);
  1489. X                if (length + len > tmplen)
  1490. X                {
  1491. X                    tmplen += len;
  1492. X                    mem_change_size(&tmp, tmplen);
  1493. X                }
  1494. X                memcpy(tmp + length, num, len);
  1495. X                length += len;
  1496. X            }
  1497. X            break;
  1498. X
  1499. X        case 'n':
  1500. X            switch (qualifier)
  1501. X            {
  1502. X            case 'l':
  1503. X                {
  1504. X                    long    *a;
  1505. X
  1506. X                    a = va_arg(ap, long *);
  1507. X                    *a = length;
  1508. X                }
  1509. X                break;
  1510. X
  1511. X            case 'h':
  1512. X                {
  1513. X                    short    *a;
  1514. X
  1515. X                    a = va_arg(ap, short *);
  1516. X                    *a = length;
  1517. X                }
  1518. X                break;
  1519. X
  1520. X            default:
  1521. X                {
  1522. X                    int    *a;
  1523. X
  1524. X                    a = va_arg(ap, int *);
  1525. X                    *a = length;
  1526. X                }
  1527. X                break;
  1528. X            }
  1529. X            break;
  1530. X
  1531. X        case 'u':
  1532. X        case 'o':
  1533. X        case 'x':
  1534. X        case 'X':
  1535. X            {
  1536. X                unsigned long    a;
  1537. X                char        num[MAX_WIDTH + 1];
  1538. X                size_t        len;
  1539. X
  1540. X                switch (qualifier)
  1541. X                {
  1542. X                case 'l':
  1543. X                    a = va_arg(ap, unsigned long);
  1544. X                    break;
  1545. X
  1546. X                case 'h':
  1547. X                    a = (unsigned short)va_arg(ap, unsigned int);
  1548. X                    break;
  1549. X
  1550. X                default:
  1551. X                    a = va_arg(ap, unsigned int);
  1552. X                    break;
  1553. X                }
  1554. X                if (!prec_set)
  1555. X                    prec = 1;
  1556. X                if (prec > MAX_WIDTH)
  1557. X                    prec = MAX_WIDTH;
  1558. X                if (width > MAX_WIDTH)
  1559. X                    width = MAX_WIDTH;
  1560. X                build_fake(fake, flag, width, prec, 'l', c);
  1561. X                sprintf(num, fake, a);
  1562. X                len = strlen(num);
  1563. X                if (length + len > tmplen)
  1564. X                {
  1565. X                    tmplen += len;
  1566. X                    mem_change_size(&tmp, tmplen);
  1567. X                }
  1568. X                memcpy(tmp + length, num, len);
  1569. X                length += len;
  1570. X            }
  1571. X            break;
  1572. X
  1573. X        case 's':
  1574. X            {
  1575. X                char    *a;
  1576. X                size_t    len;
  1577. X
  1578. X                a = va_arg(ap, char *);
  1579. X                if (prec_set)
  1580. X                {
  1581. X                    char    *ep;
  1582. X
  1583. X                    ep = (char *)memchr(a, 0, prec);
  1584. X                    if (ep)
  1585. X                        len = ep - a;
  1586. X                    else
  1587. X                        len = prec;
  1588. X                }
  1589. X                else
  1590. X                    len = strlen(a);
  1591. X                if (!prec_set || len < prec)
  1592. X                    prec = len;
  1593. X                if (!width_set || width < prec)
  1594. X                    width = prec;
  1595. X                len = width;
  1596. X                if (length + len > tmplen)
  1597. X                {
  1598. X                    tmplen += len;
  1599. X                    mem_change_size(&tmp, tmplen);
  1600. X                }
  1601. X                if (flag != '-')
  1602. X                {
  1603. X                    while (width > prec)
  1604. X                    {
  1605. X                        tmp[length++] = ' ';
  1606. X                        width--;
  1607. X                    }
  1608. X                }
  1609. X                memcpy(tmp + length, a, prec);
  1610. X                length += prec;
  1611. X                width -= prec;
  1612. X                if (flag == '-')
  1613. X                {
  1614. X                    while (width > 0)
  1615. X                    {
  1616. X                        tmp[length++] = ' ';
  1617. X                        width--;
  1618. X                    }
  1619. X                }
  1620. X            }
  1621. X            break;
  1622. X
  1623. X        case 'S':
  1624. X            {
  1625. X                string_ty    *a;
  1626. X                size_t        len;
  1627. X
  1628. X                a = va_arg(ap, string_ty *);
  1629. X                len = a->str_length;
  1630. X                if (!prec_set)
  1631. X                    prec = len;
  1632. X                if (len < prec)
  1633. X                    prec = len;
  1634. X                if (!width_set)
  1635. X                    width = prec;
  1636. X                if (width < prec)
  1637. X                    width = prec;
  1638. X                len = width;
  1639. X                if (length + len > tmplen)
  1640. X                {
  1641. X                    tmplen += len;
  1642. X                    mem_change_size(&tmp, tmplen);
  1643. X                }
  1644. X                if (flag != '-')
  1645. X                {
  1646. X                    while (width > prec)
  1647. X                    {
  1648. X                        tmp[length++] = ' ';
  1649. X                        width--;
  1650. X                    }
  1651. X                }
  1652. X                memcpy(tmp + length, a->str_text, prec);
  1653. X                length += prec;
  1654. X                width -= prec;
  1655. X                if (flag == '-')
  1656. X                {
  1657. X                    while (width > 0)
  1658. X                    {
  1659. X                        tmp[length++] = ' ';
  1660. X                        width--;
  1661. X                    }
  1662. X                }
  1663. X            }
  1664. X            break;
  1665. X        }
  1666. X    }
  1667. X
  1668. X    /*
  1669. X     * make the string
  1670. X     */
  1671. X    assert(length <= tmplen);
  1672. X    return str_n_from_c(tmp, length);
  1673. X}
  1674. END_OF_FILE
  1675. if test 22749 -ne `wc -c <'common/str.c'`; then
  1676.     echo shar: \"'common/str.c'\" unpacked with wrong size!
  1677. fi
  1678. # end of 'common/str.c'
  1679. fi
  1680. if test -f 'cook/main.c' -a "${1}" != "-c" ; then 
  1681.   echo shar: Will not clobber existing file \"'cook/main.c'\"
  1682. else
  1683. echo shar: Extracting \"'cook/main.c'\" \(17856 characters\)
  1684. sed "s/^X//" >'cook/main.c' <<'END_OF_FILE'
  1685. X/*
  1686. X *    cook - file construction tool
  1687. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  1688. X *    All rights reserved.
  1689. X *
  1690. X *    This program is free software; you can redistribute it and/or modify
  1691. X *    it under the terms of the GNU General Public License as published by
  1692. X *    the Free Software Foundation; either version 2 of the License, or
  1693. X *    (at your option) any later version.
  1694. X *
  1695. X *    This program is distributed in the hope that it will be useful,
  1696. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  1697. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1698. X *    GNU General Public License for more details.
  1699. X *
  1700. X *    You should have received a copy of the GNU General Public License
  1701. X *    along with this program; if not, write to the Free Software
  1702. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1703. X *
  1704. X * MANIFEST: operating system start point, and command line argument parsing
  1705. X */
  1706. X
  1707. X#include <stddef.h>
  1708. X#include <string.h>
  1709. X#include <stdio.h>
  1710. X#include <stdlib.h>
  1711. X
  1712. X#include <arglex.h>
  1713. X#include <builtin.h>
  1714. X#include <cook.h>
  1715. X#include <env.h>
  1716. X#include <error.h>
  1717. X#include <help.h>
  1718. X#include <id.h>
  1719. X#include <lex.h>
  1720. X#include <listing.h>
  1721. X#include <main.h>
  1722. X#include <option.h>
  1723. X#include <parse.h>
  1724. X#include <trace.h>
  1725. X#include <version.h>
  1726. X
  1727. X
  1728. Xenum
  1729. X{
  1730. X    arglex_token_action,
  1731. X    arglex_token_no_action,
  1732. X    arglex_token_book,
  1733. X    arglex_token_no_book,
  1734. X    arglex_token_errok,
  1735. X    arglex_token_no_errok,
  1736. X    arglex_token_force,
  1737. X    arglex_token_no_force,
  1738. X    arglex_token_include,
  1739. X    arglex_token_log,
  1740. X    arglex_token_no_log,
  1741. X    arglex_token_metering,
  1742. X    arglex_token_no_metering,
  1743. X    arglex_token_persevere,
  1744. X    arglex_token_no_persevere,
  1745. X    arglex_token_precious,
  1746. X    arglex_token_no_precious,
  1747. X    arglex_token_silent,
  1748. X    arglex_token_no_silent,
  1749. X    arglex_token_touch,
  1750. X    arglex_token_no_touch,
  1751. X    arglex_token_trace,
  1752. X    arglex_token_no_trace,
  1753. X    arglex_token_tty,
  1754. X    arglex_token_no_tty
  1755. X};
  1756. X
  1757. Xstatic arglex_table_ty argtab[] =
  1758. X{
  1759. X    { "-Action",        (arglex_token_ty)arglex_token_action,    },
  1760. X    { "-No_Action",        (arglex_token_ty)arglex_token_no_action, },
  1761. X    { "-Book",        (arglex_token_ty)arglex_token_book,    },
  1762. X    { "-No_Book",        (arglex_token_ty)arglex_token_no_book,    },
  1763. X    { "-Continue",        (arglex_token_ty)arglex_token_persevere, },
  1764. X    { "-No_Continue",    (arglex_token_ty)arglex_token_no_persevere, },
  1765. X    { "-Errok",        (arglex_token_ty)arglex_token_errok,    },
  1766. X    { "-No_Errok",        (arglex_token_ty)arglex_token_no_errok,    },
  1767. X    { "-Forced",        (arglex_token_ty)arglex_token_force,    },
  1768. X    { "-No_Forced",        (arglex_token_ty)arglex_token_no_force,    },
  1769. X    { "-LOg",        (arglex_token_ty)arglex_token_log,    },
  1770. X    { "-List",        (arglex_token_ty)arglex_token_log,    },
  1771. X    { "-No_LOg",        (arglex_token_ty)arglex_token_no_log,    },
  1772. X    { "-No_List",        (arglex_token_ty)arglex_token_no_log,    },
  1773. X    { "-Meter",        (arglex_token_ty)arglex_token_metering,    },
  1774. X    { "-No_Meter",        (arglex_token_ty)arglex_token_no_metering, },
  1775. X    { "-Precious",        (arglex_token_ty)arglex_token_precious,    },
  1776. X    { "-No_Precious",    (arglex_token_ty)arglex_token_no_precious, },
  1777. X    { "-Silent",        (arglex_token_ty)arglex_token_silent,    },
  1778. X    { "-No_Silent",        (arglex_token_ty)arglex_token_no_silent, },
  1779. X    { "-Touch",        (arglex_token_ty)arglex_token_touch,    },
  1780. X    { "-No_Touch",        (arglex_token_ty)arglex_token_no_touch,    },
  1781. X    { "-TRace",        (arglex_token_ty)arglex_token_trace,    },
  1782. X    { "-No_TRace",        (arglex_token_ty)arglex_token_no_trace,    },
  1783. X    { "-TErminal",        (arglex_token_ty)arglex_token_tty,    },
  1784. X    { "-No_TErminal",    (arglex_token_ty)arglex_token_no_tty,    },
  1785. X    { "-Include",        (arglex_token_ty)arglex_token_include,    },
  1786. X    { "-\\I*",        (arglex_token_ty)arglex_token_include,    },
  1787. X    { 0, (arglex_token_ty)0, }, /* end marker */
  1788. X};
  1789. X
  1790. X
  1791. X/*
  1792. X *  NAME
  1793. X *    usage - options diagnostic
  1794. X *
  1795. X *  SYNOPSIS
  1796. X *    void usage(void);
  1797. X *
  1798. X *  DESCRIPTION
  1799. X *    Usage is called when the user has made a syntactic or semantic error
  1800. X *    on the command line.
  1801. X *
  1802. X *  CAVEAT
  1803. X *    This function does NOT return.
  1804. X */
  1805. X
  1806. Xstatic void usage _((void));
  1807. X
  1808. Xstatic void
  1809. Xusage()
  1810. X{
  1811. X    fprintf(stderr, "usage: %s [ <option>... ][ <filename>... ]\n", progname);
  1812. X    fprintf(stderr, "       %s -Help\n", progname);
  1813. X    fprintf(stderr, "       %s -VERSion\n", progname);
  1814. X    quit(1);
  1815. X}
  1816. X
  1817. X
  1818. X/*
  1819. X * NAME
  1820. X *    help - give some
  1821. X *
  1822. X * SYNOPSIS
  1823. X *    void help(void);
  1824. X *
  1825. X * DESCRIPTION
  1826. X *    Help is used to provide the use with some assistance.
  1827. X *
  1828. X * RETURNS
  1829. X *    void
  1830. X *
  1831. X * CAVEAT
  1832. X *    Assumes os_get_search_rules has been called already.
  1833. X */
  1834. X
  1835. Xstatic void cook_help _((void));
  1836. X
  1837. Xstatic void
  1838. Xcook_help()
  1839. X{
  1840. X    static char *text[] =
  1841. X    {
  1842. X"NAME",
  1843. X"    %s - a file construction tool",
  1844. X"",
  1845. X"SYNOPSIS",
  1846. X"    %s [ <option>... ][ <filename>... ]",
  1847. X"    %s -Help",
  1848. X"    %s -VERSion",
  1849. X"",
  1850. X"DESCRIPTION",
  1851. X"    The %s program is a tool for constructing files.  It is",
  1852. X"    given a set of files to create, and instructions",
  1853. X"    detailing how to construct them.  In any non-trivial",
  1854. X"    program there will be prerequisites to performing the",
  1855. X"    actions necessary to creating any file, such as",
  1856. X"    extraction from a source-control system.  The %s",
  1857. X"    program provides a mechanism to define these.",
  1858. X"",
  1859. X"    When a program is being developed or maintained, the",
  1860. X"    programmer will typically change one file of several",
  1861. X"    which comprise the program.  The %s program examines",
  1862. X"    the last-modified times of the files to see when the",
  1863. X"    prerequisites of a file have changed, implying that the",
  1864. X"    file needs to be recreated as it is logically out of",
  1865. X"    date.",
  1866. X"",
  1867. X"    The %s program also provides a facility for implicit",
  1868. X"    recipes, allowing users to specify how to form a file",
  1869. X"    with a given suffix from a file with a different suffix.",
  1870. X"    For example, to create filename.o from filename.c",
  1871. X"",
  1872. X"    Options and filenames may be arbitrarily mixed on the",
  1873. X"    command line; no processing is done until all options and",
  1874. X"    filenames on the command line have been scanned.",
  1875. X"",
  1876. X"    The %s program will attempt to create the named files",
  1877. X"    from the recipes given to it.  The recipes are contained",
  1878. X"    in a file called Howto.%s in the currect directory.",
  1879. X"    This file may, in turn, include other files containing",
  1880. X"    additional recipes.",
  1881. X"",
  1882. X"    If no filenames are given on the command line the targets",
  1883. X"    of the first recipe defined are cooked.",
  1884. X"",
  1885. X"OPTIONS",
  1886. X"    The valid options for %s are listed below.  Any other",
  1887. X"    options (words on the command line beginning with `-')",
  1888. X"    will cause a diagnostic message to be issued.",
  1889. X"",
  1890. X"    -Action",
  1891. X"        Execute the commands given in the recipes.  This",
  1892. X"        is the default.",
  1893. X"",
  1894. X"    -No_Action",
  1895. X"        Do not execute the commands given in the recipes.",
  1896. X"",
  1897. X"       -Book <filename>",
  1898. X"        Tells %s to used the named cookbook, rather than",
  1899. X"        the default ``Howto.cook'' file.",
  1900. X"",
  1901. X"    -Continue",
  1902. X"        If cooking a target should fail, continue with",
  1903. X"        other recipes for which the failed target is not",
  1904. X"        an ingredient, directly or indirectly.",
  1905. X"",
  1906. X"    -No_Continue",
  1907. X"        If cooking a target should fail, %s will exit.",
  1908. X"        This is the default.",
  1909. X"",
  1910. X"    -Errok",
  1911. X"        When a command is executed, the exit code will be",
  1912. X"        ignored.",
  1913. X"",
  1914. X"    -No_Errok",
  1915. X"        When a command is executed, if the exit code is",
  1916. X"        positive it will be deemed to fail, and thus the",
  1917. X"        recipe containing it to have failed.  This is the",
  1918. X"        default.",
  1919. X"",
  1920. X"    -Force",
  1921. X"        Always perform the actions of recipes,",
  1922. X"        irrespective of the last-modified times of any of",
  1923. X"        the ingredients.  This option is useful if",
  1924. X"        something beyond the scope of the cookbook has",
  1925. X"        been modified; for example, a bug fix in a",
  1926. X"        compiler.",
  1927. X"",
  1928. X"    -No_Force",
  1929. X"        Perform the actions of the recipes if any of the",
  1930. X"        ingredients are logically out of date. This is",
  1931. X"        the default.",
  1932. X"",
  1933. X"    -Help",
  1934. X"        Provide information about how to execute %s on",
  1935. X"        stdout, and perform no other function.",
  1936. X"",
  1937. X"    -Include <filename>",
  1938. X"        Search the named directory before the standard",
  1939. X"        places for included cookbooks. Each directory so",
  1940. X"        named will be scanned in the order given.  The",
  1941. X"        standard places are $HOME/.%s then",
  1942. X"        /usr/local/lib/cook.",
  1943. X"",
  1944. X"    -List",
  1945. X"        Causes %s to automatically redirect the stdout",
  1946. X"        and stderr of the session.  Output will continue",
  1947. X"        to come to the terminal, unless %s is executing",
  1948. X"        in the background.  The name of the file will be",
  1949. X"        the name of the cookbook with any suffix removed",
  1950. X"        and \".list\" appended; this will usually be",
  1951. X"        Howto.list.  This is the default.",
  1952. X"",
  1953. X"    -List <filename>",
  1954. X"        Causes %s to automatically redirect the stdout",
  1955. X"        and stderr of the session into the named file.",
  1956. X"        Output will continue to come to the terminal,",
  1957. X"        unless %s is executing in the background.",
  1958. X"",
  1959. X"    -No_List",
  1960. X"        No automatic redirection of the output of the",
  1961. X"        session will be made.",
  1962. X"",
  1963. X"    -No_List <filename>",
  1964. X"        No automatic redirection of the output of the",
  1965. X"        session will be made, however subsequent -List",
  1966. X"        options will default to listing to the named",
  1967. X"        file.",
  1968. X"",
  1969. X"    -Meter",
  1970. X"        After each command is executed, print a summary",
  1971. X"        of the command's CPU usage.",
  1972. X"",
  1973. X"    -No_Meter",
  1974. X"        Do not print a CPU usage summary after each",
  1975. X"        command.  This is the default.",
  1976. X"",
  1977. X"    -Precious",
  1978. X"        When commands in the body of a recipe fail, do",
  1979. X"        not delete the targets of the recipe.",
  1980. X"",
  1981. X"    -No_Precious",
  1982. X"        When commands in the body of a recipe fail,",
  1983. X"        delete the targets of the recipe.  This is the",
  1984. X"        default.",
  1985. X"",
  1986. X"    -Silent",
  1987. X"        Do not echo commands before they are executed.",
  1988. X"",
  1989. X"    -No_Silent",
  1990. X"        Echo commands before they are executed.  This is",
  1991. X"        the default.",
  1992. X"",
  1993. X"    -Touch",
  1994. X"        Update the last-modified times of the target",
  1995. X"        files, rather than execute the actions bound to",
  1996. X"        recipes.  This can be useful if you have made a",
  1997. X"        modification to a file that you know will make a",
  1998. X"        system of files logically out of date, but has no",
  1999. X"        significance; for example, adding a comment to a",
  2000. X"        widely used include file.",
  2001. X"",
  2002. X"    -No_Touch",
  2003. X"        Execute the actions bound to recipes, rather than",
  2004. X"        update the last-modified times of the target",
  2005. X"        files. This is the default.",
  2006. X"",
  2007. X"    -TErminal",
  2008. X"        When listing, also send the output stream to the",
  2009. X"        terminal.  This is the default.",
  2010. X"",
  2011. X"    -No_TErminal",
  2012. X"        When listing, do not send the output to the",
  2013. X"        terminal.",
  2014. X"",
  2015. X"    name=value",
  2016. X"        Assign the value to the named variable.  The",
  2017. X"        value may contain spaces if you can convince the",
  2018. X"        shell to pass them through.",
  2019. X"",
  2020. X"    -TRace",
  2021. X"        Two options are provided for tracing the",
  2022. X"        inferences %s makes when attempting to %s a",
  2023. X"        target.  The -TRace option will cause %s will",
  2024. X"        emit copious amounts of information about the",
  2025. X"        inferences it is making when cooking targets.",
  2026. X"        This option may be used when you think %s is",
  2027. X"        acting strangely, or are just curious.",
  2028. X"",
  2029. X"    -No_TRace",
  2030. X"        This option may be used to cause %s will not",
  2031. X"        emit information about the inferences it is",
  2032. X"        making when cooking targets.  This is the",
  2033. X"        default.",
  2034. X"",
  2035. X"    All options may be abbreviated; the abbreviation is",
  2036. X"    documented as the upper case letters, all lower case",
  2037. X"    letters and underscores (_) are optional.  You must use",
  2038. X"    consecutive sequences of optional letters.",
  2039. X"",
  2040. X"    All options are case insensitive, you may type them in",
  2041. X"    upper case or lower case or a combination of both, case",
  2042. X"    is not important.",
  2043. X"",
  2044. X"    For example: the arguments \"-help\", \"-HEL\" and \"-h\" are",
  2045. X"    all interpreted to mean the -Help option.  The argument",
  2046. X"    \"-hlp\" will not be understood, because consecutive",
  2047. X"    optional characters were not supplied.",
  2048. X"",
  2049. X"    Options and other command line arguments may be mixed",
  2050. X"    arbitrarily on the command line.",
  2051. X"",
  2052. X"    The GNU long option names are understood.  Since all",
  2053. X"    option names for %s are long, this means ignoring the",
  2054. X"    extra leading '-'.  The \"--option=value\" convention is",
  2055. X"    also understood.",
  2056. X"",
  2057. X"EXIT STATUS",
  2058. X"    The %s command will exit with a status of 1 on any",
  2059. X"    error.  The %s command will only exit with a status of",
  2060. X"    0 if there are no errors.",
  2061. X"",
  2062. X"COPYRIGHT",
  2063. X"    %C",
  2064. X"",
  2065. X"AUTHOR",
  2066. X"    %A",
  2067. X    };
  2068. X
  2069. X    help(text, SIZEOF(text), usage);
  2070. X}
  2071. X
  2072. X
  2073. X/*
  2074. X * NAME
  2075. X *    argparse - parse command line
  2076. X *
  2077. X * SYNOPSIS
  2078. X *    void argparse(option_level_ty);
  2079. X *
  2080. X * DESCRIPTION
  2081. X *    The argparse function is used to parse command lines.
  2082. X *
  2083. X * RETURNS
  2084. X *    void
  2085. X */
  2086. X
  2087. Xstatic void argparse _((option_level_ty));
  2088. X
  2089. Xstatic void
  2090. Xargparse(level)
  2091. X    option_level_ty    level;
  2092. X{
  2093. X    option_number_ty    type = -1;
  2094. X
  2095. X    switch (arglex())
  2096. X    {
  2097. X    case arglex_token_help:
  2098. X        if (level != OPTION_LEVEL_COMMAND_LINE)
  2099. X            fatal("may not use %s in environment variable", arglex_value.alv_string);
  2100. X        cook_help();
  2101. X        quit(0);
  2102. X    
  2103. X    case arglex_token_version:
  2104. X        if (level != OPTION_LEVEL_COMMAND_LINE)
  2105. X            fatal("may not use %s in environment variable", arglex_value.alv_string);
  2106. X        version();
  2107. X        quit(0);
  2108. X
  2109. X    default:
  2110. X        break;
  2111. X    }
  2112. X    while (arglex_token != arglex_token_eoln)
  2113. X    {
  2114. X        switch (arglex_token)
  2115. X        {
  2116. X        default:
  2117. X            error
  2118. X            (
  2119. X                "misplaced \"%s\" command line argument",
  2120. X                arglex_value.alv_string
  2121. X            );
  2122. X            usage();
  2123. X
  2124. X#ifdef DEBUG
  2125. X        case arglex_token_tracing:
  2126. X            if (arglex() != arglex_token_string)
  2127. X                fatal("-TRACIng requires one or more string arguments");
  2128. X            for (;;)
  2129. X            {
  2130. X                trace_enable(arglex_value.alv_string);
  2131. X                if (arglex() != arglex_token_string)
  2132. X                    break;
  2133. X            }
  2134. X            continue;
  2135. X#endif
  2136. X
  2137. X        case arglex_token_include:
  2138. X            {
  2139. X                string_ty *s;
  2140. X
  2141. X                if (arglex() != arglex_token_string)
  2142. X                    fatal("-Include requires a string argument");
  2143. X                s = str_from_c(arglex_value.alv_string);
  2144. X                wl_append_unique(&option.o_search_path, s);
  2145. X                str_free(s);
  2146. X            }
  2147. X            break;
  2148. X
  2149. X        case arglex_token_trace:
  2150. X            type = OPTION_TRACE;
  2151. X            normal_on:
  2152. X            if (option_already(type, level))
  2153. X                too_many:
  2154. X                fatal("too many \"%s\" options", arglex_value.alv_string);
  2155. X            option_set(type, level, 1);
  2156. X            break;
  2157. X
  2158. X        case arglex_token_no_trace:
  2159. X            type = OPTION_TRACE;
  2160. X            normal_off:
  2161. X            if (option_already(type, level))
  2162. X                goto too_many;
  2163. X            option_set(type, level, 0);
  2164. X            break;
  2165. X
  2166. X        case arglex_token_tty:
  2167. X            type = OPTION_TERMINAL;
  2168. X            goto normal_on;
  2169. X
  2170. X        case arglex_token_no_tty:
  2171. X            type = OPTION_TERMINAL;
  2172. X            goto normal_off;
  2173. X
  2174. X        case arglex_token_precious:
  2175. X            type = OPTION_PRECIOUS;
  2176. X            goto normal_on;
  2177. X
  2178. X        case arglex_token_no_precious:
  2179. X            type = OPTION_PRECIOUS;
  2180. X            goto normal_off;
  2181. X
  2182. X        case arglex_token_log:
  2183. X            if (option_already(OPTION_LOGGING, level))
  2184. X                goto too_many;
  2185. X            option_set(OPTION_LOGGING, level, 1);
  2186. X            if (arglex() != arglex_token_string)
  2187. X                continue;
  2188. X            if (option.o_logfile)
  2189. X                str_free(option.o_logfile);
  2190. X            option.o_logfile = str_from_c(arglex_value.alv_string);
  2191. X            break;
  2192. X
  2193. X        case arglex_token_no_log:
  2194. X            type = OPTION_LOGGING;
  2195. X            goto normal_off;
  2196. X
  2197. X        case arglex_token_book:
  2198. X            if (option_already(OPTION_BOOK, level))
  2199. X                goto too_many;
  2200. X            option_set(OPTION_BOOK, level, 1);
  2201. X            if (arglex() != arglex_token_string)
  2202. X                continue;
  2203. X            if (option.o_book)
  2204. X                str_free(option.o_book);
  2205. X            option.o_book = str_from_c(arglex_value.alv_string);
  2206. X            break;
  2207. X
  2208. X        case arglex_token_no_book:
  2209. X            type = OPTION_BOOK;
  2210. X            goto normal_off;
  2211. X
  2212. X        case arglex_token_silent:
  2213. X            type = OPTION_SILENT;
  2214. X            goto normal_on;
  2215. X
  2216. X        case arglex_token_no_silent:
  2217. X            type = OPTION_SILENT;
  2218. X            goto normal_off;
  2219. X
  2220. X        case arglex_token_metering:
  2221. X            type = OPTION_METER;
  2222. X            goto normal_on;
  2223. X
  2224. X        case arglex_token_no_metering:
  2225. X            type = OPTION_METER;
  2226. X            goto normal_off;
  2227. X
  2228. X        case arglex_token_touch:
  2229. X            type = OPTION_TOUCH;
  2230. X            goto normal_on;
  2231. X
  2232. X        case arglex_token_no_touch:
  2233. X            type = OPTION_TOUCH;
  2234. X            goto normal_off;
  2235. X
  2236. X        case arglex_token_action:
  2237. X            type = OPTION_ACTION;
  2238. X            goto normal_on;
  2239. X
  2240. X        case arglex_token_no_action:
  2241. X            type = OPTION_ACTION;
  2242. X            goto normal_off;
  2243. X
  2244. X        case arglex_token_persevere:
  2245. X            type = OPTION_PERSEVERE;
  2246. X            goto normal_on;
  2247. X
  2248. X        case arglex_token_no_persevere:
  2249. X            type = OPTION_PERSEVERE;
  2250. X            goto normal_off;
  2251. X
  2252. X        case arglex_token_errok:
  2253. X            type = OPTION_ERROK;
  2254. X            goto normal_on;
  2255. X
  2256. X        case arglex_token_no_errok:
  2257. X            type = OPTION_ERROK;
  2258. X            goto normal_off;
  2259. X
  2260. X        case arglex_token_force:
  2261. X            type = OPTION_FORCE;
  2262. X            goto normal_on;
  2263. X
  2264. X        case arglex_token_no_force:
  2265. X            type = OPTION_FORCE;
  2266. X            goto normal_off;
  2267. X
  2268. X        case arglex_token_string:
  2269. X            {
  2270. X                char    *cp;
  2271. X
  2272. X                cp = strchr(arglex_value.alv_string, '=');
  2273. X                if (!cp)
  2274. X                {
  2275. X                    string_ty    *s;
  2276. X    
  2277. X                    s = str_from_c(arglex_value.alv_string);
  2278. X                    wl_append(&option.o_target, s);
  2279. X                    str_free(s);
  2280. X                }
  2281. X                else
  2282. X                {
  2283. X                    wlist        wl;
  2284. X                    string_ty    *name;
  2285. X                    string_ty    *value;
  2286. X    
  2287. X                    name = str_n_from_c(
  2288. X                        arglex_value.alv_string,
  2289. X                        cp - arglex_value.alv_string
  2290. X                    ); 
  2291. X                    value = str_from_c(cp + 1);
  2292. X                    str2wl(&wl, value);
  2293. X                    str_free(value);
  2294. X                    id_assign(name, ID_CLASS_VARIABLE, &wl);
  2295. X                    str_free(name);
  2296. X                    wl_free(&wl);
  2297. X                }
  2298. X            }
  2299. X            break;
  2300. X        }
  2301. X        arglex();
  2302. X    }
  2303. X}
  2304. X
  2305. X
  2306. X/*
  2307. X * NAME
  2308. X *    main - initial entry point for cook
  2309. X *
  2310. X * SYNOPSIS
  2311. X *    void main(int argc, char **argv);
  2312. X *
  2313. X * DESCRIPTION
  2314. X *    Main is the initial entry point for cook.
  2315. X *
  2316. X * RETURNS
  2317. X *    Exit is always through exit().
  2318. X *    The exit code will be 0 for success, or 1 for some error.
  2319. X */
  2320. X
  2321. Xint main _((int, char **));
  2322. X
  2323. Xint
  2324. Xmain(argc, argv)
  2325. X    int        argc;
  2326. X    char        **argv;
  2327. X{
  2328. X    int        retval;
  2329. X
  2330. X    /*
  2331. X     * initialize things
  2332. X     * (order is critical here)
  2333. X     */
  2334. X#ifdef TIMING
  2335. X    os_totals_start();
  2336. X#endif
  2337. X    arglex_set_progname(argv[0]);
  2338. X    env_initialize();
  2339. X    str_initialize();
  2340. X    id_initialize(); 
  2341. X    builtin_initialize();
  2342. X    lex_initialize();
  2343. X    parse_initialize();
  2344. X
  2345. X    /*
  2346. X     * parse the command line
  2347. X     */
  2348. X    arglex_init_from_env(argv[0], argtab);
  2349. X    argparse(OPTION_LEVEL_ENVIRONMENT);
  2350. X
  2351. X    /*
  2352. X     * parse the command line
  2353. X     */
  2354. X    arglex_init(argc, argv, argtab);
  2355. X    argparse(OPTION_LEVEL_COMMAND_LINE);
  2356. X
  2357. X    option_tidy_up();
  2358. X
  2359. X    log_open();
  2360. X
  2361. X    /*
  2362. X     * read in the cook book
  2363. X     */
  2364. X    if (!option.o_book)
  2365. X        fatal("no book found");
  2366. X    parse(option.o_book);
  2367. X
  2368. X    /*
  2369. X     * work out what to cook.
  2370. X     * If no targets have been given, use the first explicit recipe.
  2371. X     */
  2372. X    if (!option.o_target.wl_nwords)
  2373. X    {
  2374. X        if (!explicit.rl_nrecipes)
  2375. X            fatal("no default target");
  2376. X        wl_copy(&option.o_target, &explicit.rl_recipe[0].r_target);
  2377. X    }
  2378. X    assert(option.o_target.wl_nwords);
  2379. X
  2380. X    retval = cook(&option.o_target);
  2381. X
  2382. X#ifdef TIMING
  2383. X    os_totals();
  2384. X#endif
  2385. X    quit(retval);
  2386. X    /*NOTREACHED*/
  2387. X    return 0;
  2388. X}
  2389. END_OF_FILE
  2390. if test 17856 -ne `wc -c <'cook/main.c'`; then
  2391.     echo shar: \"'cook/main.c'\" unpacked with wrong size!
  2392. fi
  2393. # end of 'cook/main.c'
  2394. fi
  2395. if test -f 'doc/language' -a "${1}" != "-c" ; then 
  2396.   echo shar: Will not clobber existing file \"'doc/language'\"
  2397. else
  2398. echo shar: Extracting \"'doc/language'\" \(18062 characters\)
  2399. sed "s/^X//" >'doc/language' <<'END_OF_FILE'
  2400. X.\"
  2401. X.\"    cook - file construction tool
  2402. X.\"    Copyright (C) 1990, 1991, 1992, 1993 Peter Miller.
  2403. X.\"    All rights reserved.
  2404. X.\"
  2405. X.\"    This program is free software; you can redistribute it and/or modify
  2406. X.\"    it under the terms of the GNU General Public License as published by
  2407. X.\"    the Free Software Foundation; either version 2 of the License, or
  2408. X.\"    (at your option) any later version.
  2409. X.\"
  2410. X.\"    This program is distributed in the hope that it will be useful,
  2411. X.\"    but WITHOUT ANY WARRANTY; without even the implied warranty of
  2412. X.\"    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2413. X.\"    GNU General Public License for more details.
  2414. X.\"
  2415. X.\"    You should have received a copy of the GNU General Public License
  2416. X.\"    along with this program; if not, write to the Free Software
  2417. X.\"    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2418. X.\"
  2419. X.\" MANIFEST: Reference Manual, Cookbook Lanuage Definition
  2420. X.\"    
  2421. X.H 1 "Cookbook Language Definition"
  2422. XThis chapter defines that language which cookbooks
  2423. Xare written in.
  2424. XWhile some of its properties are similar to C,
  2425. Xdo not be misled.
  2426. X.P
  2427. XA number of sections appear within this chapter.
  2428. X.AL
  2429. X.LI
  2430. XThe
  2431. X.I "Lexical Analysis"
  2432. Xsection describes what the words of the cookbook language look like.
  2433. X.LI
  2434. XThe
  2435. X.I Preprocessor 
  2436. Xsection describes
  2437. Xthe include mechanism
  2438. Xand the conditional compilation mechanism.
  2439. X.LI
  2440. XThe 
  2441. X.I "Syntax Descriptions"
  2442. Xsection describes how to read the syntax definitions
  2443. Xin the following section.
  2444. X.LI
  2445. XThe 
  2446. X.I "Syntax and Semantics"
  2447. Xsection describes
  2448. Xhow words in the cookbook may be combined to form valid constructs
  2449. X(the
  2450. X.IR syntax ),
  2451. Xand what these constructs
  2452. Xmean (the
  2453. X.IR semantics ).
  2454. X.LE
  2455. X.P
  2456. XThe sections are laid out in the recommended reading order.
  2457. X.SK
  2458. X.H 2 "Lexical Analysis"
  2459. XThe cookbook is made of a number of recipes,
  2460. Xwhich are in turn made of words.
  2461. XThis section describes what constitutes a word, and what does not.
  2462. X.H 3 "Words and Keywords"
  2463. XWords are made of sequences of almost any character,
  2464. Xand are separated by white space (including end-of-line) or the
  2465. Xspecial symbols.
  2466. X.B Cook
  2467. Xis always case sensitive
  2468. Xwhen reading cookbooks.
  2469. X.P
  2470. XThe characters 
  2471. X.B ":;={}[]"
  2472. Xare the special symbols,
  2473. Xand are words in themselves,
  2474. Xneeding no delimiting.
  2475. X.P
  2476. XIn addition to the special symbols,
  2477. Xsome words,
  2478. Xknown as
  2479. X.IR keywords ,
  2480. Xhave special meaning to
  2481. X.BR cook .
  2482. XThe keywords are:
  2483. X.TS
  2484. Xcenter, tab(;);
  2485. Xce ce ce ce.
  2486. Xif;then;else;set
  2487. Xloop;loopstop;fail;unsetenv
  2488. X.TE
  2489. XYou will meet the keywords in later sections.
  2490. X.H 3 "Escape Sequences"
  2491. XThe character
  2492. X.B \e
  2493. Xis the
  2494. X.I escape
  2495. Xcharacter.
  2496. XIf a character is preceded by a
  2497. X.B \e 
  2498. Xany specialness,
  2499. Xif it had any,
  2500. Xwill be removed.
  2501. XIf it had no specialness it may have some added.
  2502. X.P
  2503. XThis means that,
  2504. Xif you want to use
  2505. X.B if
  2506. Xas a word,
  2507. Xrather than a keyword,
  2508. Xat least one of its characters needs to be escaped,
  2509. Xfor example
  2510. X.BR \eif .
  2511. X.P
  2512. XThe escape sequences which are special are as follows.
  2513. X.TS
  2514. Xcenter, tab(;);
  2515. Xcf(B) lw(2.2i).
  2516. X\eb;The backspace character
  2517. X\ef;The form feed character
  2518. X\en;The newline or linefeed character
  2519. X\er;The carriage return character
  2520. X\et;The horizontal tab character
  2521. X\e\fInnn\fP;T{
  2522. XA character with a value of
  2523. X.IR nnn ,
  2524. Xwhere
  2525. X.I nnn
  2526. Xis an octal number of at most 3 digits.
  2527. XT}
  2528. X.TE
  2529. XAn escaped end-of-line is totally ignored.
  2530. XIt should be noted that a cookbook may not have any non-printing
  2531. Xascii characters in it other than space, tab and end-of-line.
  2532. X.H 3 "Quoting"
  2533. XWords, and sections of words, may be quoted.
  2534. XIf any part of a word is quoted it cannot be a keyword.
  2535. X.P
  2536. XThis means that,
  2537. Xif you want to use
  2538. X.B if
  2539. Xas a word, rather than a keyword,
  2540. Xat least one of its characters needs to be quoted,
  2541. Xfor example
  2542. X.BR "\&'if'" .
  2543. X.P
  2544. XBoth single
  2545. X.RB ( ' )
  2546. Xand double
  2547. X.RB ( \\" )
  2548. Xquotes are understood by
  2549. X.BR cook ,
  2550. Xand one may enclose the other.
  2551. XIf a quote is escaped it does not open or close a quote as it usually
  2552. Xwould.
  2553. X.P
  2554. X.B Cook
  2555. Xdoes not like newlines within quotes.
  2556. XThis is a generally good heuristic for catching unbalanced quotes.
  2557. X.H 3 "Comments"
  2558. XComments are delimited on the left by
  2559. X.BR /* ,
  2560. Xand on the right by
  2561. X.BR */ ,
  2562. XIf the
  2563. X.B /
  2564. Xcharacter has been escaped or quoted,
  2565. Xit doesn't introduce a comment.
  2566. XComments may be nested.
  2567. XComments may span multiple lines.
  2568. XComments are replaced by one logical space.
  2569. X.SK
  2570. X.H 2 "Preprocessor"
  2571. XThe preprocessor may be thought of as doing a little work before the
  2572. X.I "Syntax and Semantics"
  2573. Xsection has its turn.
  2574. X.P
  2575. XThe preprocessor is driven by
  2576. X.IR "preprocessor directives" .
  2577. XA preprocessor directive is a line 
  2578. Xwhich starts with a hash 
  2579. X.RB ( # )
  2580. Xcharacter.
  2581. XEach of the preprocessor directives is described below.
  2582. X.H 3 "include"
  2583. XThe most common preprocessor directive is
  2584. X.eB
  2585. X#include "\f(CIfilename\fP"
  2586. X.eE
  2587. X.P
  2588. XThis preprocessor directive is processed as if the contents
  2589. Xof the named file had appeared in the cookbook,
  2590. Xrather than the preprocessor include directive.
  2591. X.P
  2592. XThe most common use of the #include directive is to include
  2593. Xsystem cookbooks.
  2594. X.P
  2595. XThe standard places to search are first any path specified with the
  2596. X.B -Include
  2597. Xcommand line option,
  2598. Xand then
  2599. X.I $HOME/.cook
  2600. Xand
  2601. Xthen
  2602. X.IR /usr/local/lib/cook 
  2603. Xin that order.
  2604. X.H 3 "if"
  2605. XThe #if directive may be used to conditionally pass tokens to
  2606. Xthe syntax and semantics processing.
  2607. XDirectives take the form
  2608. X.eB
  2609. X#if \fIexpression1\fP
  2610. X\fIsomething1\fP
  2611. X#elif \fIexpression2\fP
  2612. X\fIsomething2\fP
  2613. X#else
  2614. X\fIsomething3\fP
  2615. X#endif
  2616. X.eE
  2617. XThere may be any number of \f(CWelif\fP clauses,
  2618. Xand the \f(CWelse\fP
  2619. Xclause is optional.
  2620. XOnly one of the 
  2621. X.I somethings
  2622. Xwill be passed through.
  2623. X.H 3 "ifdef"
  2624. XThis directive takes a similar form to the \f(CWif\fP directive,
  2625. Xbut with a different first line:
  2626. X.eB
  2627. X#ifdef \fIvariable\fP
  2628. X.eE
  2629. XThis is syntactic sugar for
  2630. X.eB
  2631. X#if [defined \fIsymbol\fP]
  2632. X.eE
  2633. XThis is of most use in bracketing \f(CW#include\fP directives.
  2634. X.H 3 "ifndef"
  2635. XThis directive takes a similar form to the \f(CWif\fP directive,
  2636. Xbut with a different first line:
  2637. X.eB
  2638. X#ifndef \fIvariable\fP
  2639. X.eE
  2640. XThis is syntactic sugar for
  2641. X.eB
  2642. X#if [not [defined \fIsymbol\fP]]
  2643. X.eE
  2644. XThis is of most use in bracketing \f(CW#include\fP directives.
  2645. X.H 3 "pragma"
  2646. XThis is for the addition of extensions.
  2647. X.H 4 "once"
  2648. XThis directive is to ensure that include files in which it appears are included exactly once.
  2649. X.P
  2650. XThis directive has the form
  2651. X.eB
  2652. X#pragma once
  2653. X.eE
  2654. X.H 4 "unknown extensions"
  2655. XAny extensions not recognised will be ignored.
  2656. X.SK
  2657. X.H 2 "Syntax Descriptions"
  2658. XIn the syntax descriptions which follow
  2659. Xthere are several meta symbols,
  2660. Xdefined as follows.
  2661. X.TS
  2662. Xcenter, tab(;);
  2663. Xcf(B) lw(2.5i).
  2664. X\&=;A definition symbol.
  2665. X\&|;The alternative symbol.
  2666. X\&.;The end-of-production symbol.
  2667. X\&/*\fItext\fB*/;This is a comment.
  2668. X\&'\fItext\fB';T{
  2669. XThe
  2670. X.I text
  2671. Xis a literal terminal symbol of the grammar being defined.
  2672. XT}
  2673. X.TE
  2674. X.P
  2675. XLike all real languages,
  2676. Xthe format is free form,
  2677. Xno columns or end-of-line are significant.
  2678. X.P
  2679. XAs an example, the syntax description format is described using itself.
  2680. X.eB
  2681. Xsyntax
  2682. X    = /* empty */
  2683. X    | syntax production
  2684. X    .
  2685. X.eE
  2686. XA syntax definition may consist of zero or more productions.
  2687. X.eB
  2688. Xproduction
  2689. X    = name '\fB=\fP' term '\fB.\fP'
  2690. X    .
  2691. X.eE
  2692. XA production names a non-terminal symbol of the grammar being defined
  2693. Xon the left,
  2694. Xand its expansion on the right.
  2695. X.eB
  2696. Xterm
  2697. X    = factor
  2698. X    | term \fB'|'\fP term
  2699. X    .
  2700. X.eE
  2701. XA term may consist of a factor;
  2702. Xor
  2703. Xa term may consist of zero or more of the above terms
  2704. Xseparated by
  2705. X.I alternative
  2706. Xsymbols.
  2707. X.eB
  2708. Xfactor
  2709. X    = /* empty */
  2710. X    | factor name
  2711. X    | factor literal
  2712. X    .
  2713. X.eE
  2714. XA factor consists of
  2715. Xzero or more symbol names (terminal or non-terminal)
  2716. Xor literals in a row.
  2717. X.P
  2718. XA symbol is terminal if it is not named on the left-hand-side of a production,
  2719. Xor it is a literal.
  2720. X.SK
  2721. X.H 2 "Syntax and Semantics"
  2722. X.H 3 "Overall Structure"
  2723. XThe general form of the cookbook is defined as
  2724. X.eB
  2725. Xcookbook
  2726. X    = /* empty */
  2727. X    | cookbook statement
  2728. X    .
  2729. X.eE
  2730. XA cookbook is defined as a sequence of statements.
  2731. XEach statement statement is executed.
  2732. XFor a definition of what it means when a statement is executed,
  2733. Xsee the individual statement definitions.
  2734. X.P
  2735. XThe nonterminal symbol
  2736. X.I statement
  2737. Xwill be defined in the sections below.
  2738. X.P
  2739. XPlease note that a statement is not always evaluated when is is read,
  2740. Xbut at specific, well defined times.
  2741. X.H 3 "The Compound Statement"
  2742. XA nonterminal symbol which will be referred to below is the
  2743. X.I compound_statement
  2744. Xsymbol,
  2745. Xdefined as follows:
  2746. X.eB
  2747. Xcompound_statement
  2748. X    = '\fB{\fP' statements '\fB}\fP'
  2749. X    .
  2750. Xstatements
  2751. X    = /* empty */
  2752. X    | statements statement
  2753. X    .
  2754. X.eE
  2755. XThe compound statement may be used anywhere a statement may be,
  2756. Xand in particular
  2757. X.eB
  2758. Xstatement
  2759. X    = compound_statement
  2760. X    .
  2761. X.eE
  2762. X.H 3 "Variables and Expressions"
  2763. X.B Cook
  2764. Xprovides variables to the user to simplify things.
  2765. X.H 4 "The Assignment Statement"
  2766. XIt is possible to assign to variables with the following statement.
  2767. X.eB
  2768. Xstatement
  2769. X    = expr '\fB=\fP' exprs '\fB;\fP'
  2770. X    .
  2771. X.eE
  2772. XWhen this statement is executed,
  2773. Xthe variable whose name the left hand expression evaluates to will be
  2774. Xassigned the value that the right hand expression list evaluates to.
  2775. X.H 4 "Expressions"
  2776. XMany definitions make reference to the
  2777. X.IR expr,
  2778. X.I elist
  2779. Xand
  2780. X.I exprs
  2781. Xnonterminal symbols.
  2782. XThese are defined as follows.
  2783. X.P
  2784. XThe 
  2785. X.I elist
  2786. Xis a list of at least one expression,
  2787. Xwhereas the
  2788. X.I exprs
  2789. Xis a list of zero or more expressions.
  2790. X.eB
  2791. Xelist
  2792. X    = expr
  2793. X    | elist expr
  2794. X    .
  2795. Xexprs
  2796. X    = /* empty */
  2797. X    | exprs expr
  2798. X    .
  2799. X.eE
  2800. X.P
  2801. XAn expression is composed of variable references,
  2802. Xfunction invocations,
  2803. Xwords,
  2804. Xor concatenation of expressions.
  2805. XThe concatenation is implied by abutting the two parts of the expression
  2806. Xtogether,
  2807. Xe.g.: "\f(CW[fred]>thing\fP" is an
  2808. Xindirection on
  2809. X.I fred
  2810. Xconcatenated with the literal word "\f(CW>thing\fP".
  2811. X.eB
  2812. Xexpr
  2813. X    = WORD
  2814. X    | '\fB[\fP' elist '\fB]\fP'
  2815. X    | expr \fIcat\fP expr
  2816. X    .
  2817. X.eE
  2818. X.P
  2819. XWhen an
  2820. X.BI [ elist ]
  2821. Xexpression is evaluated,
  2822. Xthe
  2823. X.I elist
  2824. Xis evaluated first.
  2825. XIf the result is a single word, then a variable of that name is
  2826. Xsearched for.
  2827. XIf found the value of an expression of this form is the value of the variable.
  2828. X.P
  2829. XIf there is no variable of the given name,
  2830. Xor the
  2831. X.I elist
  2832. Xevaluated to more than one word,
  2833. Xthe first word is taken to be a built-in function name.
  2834. XIf there is no function of this name it is an error.
  2835. X.P
  2836. XThe
  2837. X.I cat
  2838. Xoperator works as one would expect,
  2839. Xjoining the last word of the left
  2840. Xexpression and the first word of the right expression together,
  2841. Xand otherwise leaving the order of the expressions alone.
  2842. XOne usually uses the trivial case of single word expressions.
  2843. X.H 3 "Recipes"
  2844. XA number of forms of
  2845. X.I statement
  2846. Xare concerned with telling
  2847. X.B cook
  2848. Xhow to cook things.
  2849. XThere are three forms,
  2850. Xthe 
  2851. X.I explicit
  2852. Xrecipe,
  2853. Xthe
  2854. X.I implicit
  2855. Xrecipe,
  2856. Xand the
  2857. X.I ingredients
  2858. Xrecipe.
  2859. X.H 4 "The Explicit Recipe Statement"
  2860. XThe explicit recipe has the form
  2861. X.eB
  2862. Xstatement
  2863. X    = elist '\fB:\fP' exprs flags compound_statement
  2864. X    .
  2865. X.eE
  2866. XThe target(s) of the recipe are to the left of the colon,
  2867. Xand the ingredients, if any, are to the right.
  2868. XThe statements, usually commands, to perform to cook the target(s)
  2869. Xare contained in the compound statement.
  2870. XThe expressions are only evaluated into words when the recipe is
  2871. Xinstanciated.
  2872. X.P
  2873. XThe \fIflags\fP are defined as follows.
  2874. X.eB
  2875. Xflags
  2876. X    = /* empty */
  2877. X    | '\fBset\fP' words
  2878. X    .
  2879. X.eE
  2880. XA number of flags may be used
  2881. X.VL 1i
  2882. X.LI errok
  2883. XIf the errok flag is specified,
  2884. Xthe commands within the actions bound to the recipe will always be successful.
  2885. X.LI forced
  2886. XIf the forced flag is specified,
  2887. Xthe actions bound to the recipe will always be evaluated.
  2888. X.LI precious
  2889. XIf the precious flag is specified,
  2890. Xif the actions bound to the recipe fail,
  2891. Xthe targets of the recipe will not be deleted,
  2892. Xas is the default.
  2893. X.LI silent
  2894. XIf the silent flag is specified,
  2895. Xthe command within the actions bound to the recipe will not be echoed.
  2896. X.LI wildpath
  2897. XIf the wildpath flag is specified in an implicit recipe,
  2898. Xleading path on pattern matches will be prepended to reconstructions.
  2899. X.LI meter
  2900. XIf the meter flag is specified,
  2901. Xa summary of the CPU usage by the commands within this recipe
  2902. Xwill be printed after each command.
  2903. XThe silent options override this option.
  2904. X.LI clearstat
  2905. XThe date-time-modified of the files named in executed commands will be 
  2906. Xremoved from the time cache.
  2907. XThis is essential for commands such as
  2908. X.IR rm (1)
  2909. Xand
  2910. X.IR mv (1).
  2911. X.LE
  2912. X.H 4 "The Implicit Recipe Statement"
  2913. XImplicit recipes are distinguished from explicit recipes in that 
  2914. Xand implicit recipe has a target with a '\fB%\fP' character in it.
  2915. X.H 5 "Simple Form"
  2916. X.P
  2917. XIn general the user will rarely need to use the implicit recipe
  2918. Xform, as there are a huge range of implicit recipes already
  2919. Xdefined in the system default recipes.
  2920. X.P
  2921. XAn example of this recipe form is
  2922. X.eB
  2923. X%: %.Z
  2924. X    {
  2925. X    uncompress %;
  2926. X    }
  2927. X.eE
  2928. XThis recipe tells 
  2929. X.B cook
  2930. Xhow to use the
  2931. X.IR uncompress (1)
  2932. Xprogram.
  2933. X.H 5 "Complex Form"
  2934. XThe implicit recipe recipe has a second form
  2935. X.eB
  2936. Xstatement
  2937. X    = elist '\fB:\fP' exprs1 '\fB:\fP' exprs2 flags compound_statement
  2938. X    .
  2939. X.eE
  2940. XIn this form,
  2941. Xthe ingredients specified in
  2942. X.I exprs1
  2943. Xare used to determine the applicability of the recipe;
  2944. Xif these are all constructable then the recipe will be applied,
  2945. Xif any are not constructable then the recipe will not be applied.
  2946. XIf the recipe is applied,
  2947. Xthe ingredients specified in
  2948. X.I exprs2
  2949. Xare required to be constructable.
  2950. XThe 
  2951. X.I exprs2
  2952. Xsection is known as the
  2953. X.I "forced ingredients"
  2954. Xsection.
  2955. X.P
  2956. XAn example of this is the C recipe
  2957. X.eB
  2958. X%.o: %.c: [collect c_incl %.c]
  2959. X    {
  2960. X    cc -c %.c;
  2961. X    }
  2962. X.eE
  2963. XThis recipe is applied if the 
  2964. X.I %.c
  2965. Xfile can be constructed,
  2966. Xand is not applied if it cannot be constructed.
  2967. XThe include dependencies are only expressed if the recipe
  2968. Xis going to be applied;
  2969. Xbut if they are expressed, they
  2970. X.I must
  2971. Xbe constructable.
  2972. XThis means that absent include files generate an error.
  2973. X.P
  2974. XThe naive form of this recipe
  2975. X.eB
  2976. X%.o: %.c [collect c_incl %.c]
  2977. X    {
  2978. X    cc -c %.c;
  2979. X    }
  2980. X.eE
  2981. Xwill attempt to apply the
  2982. X.I c_incl
  2983. Xcommand before the
  2984. X.I %.c
  2985. Xfile is guaranteed to exist.
  2986. XThis is because the 
  2987. X.I exprs2
  2988. Xis performed after the
  2989. X.I exprs1
  2990. Xall exist (because they are constructable, they have been constructed).
  2991. XIn this naive form,
  2992. Xabsent include files result in the recipe not being applied.
  2993. X.H 4 "The Ingredients Recipe Statement"
  2994. XThe ingredients recipe has the form
  2995. X.eB
  2996. Xstatement
  2997. X    = elist '\fB:\fP' elist '\fB;\fP'
  2998. X    .
  2999. X.eE
  3000. XThe target(s) of the recipe are to the left of the colon,
  3001. Xand the prerequisites are to the right.
  3002. XThere are no statements to perform to cook the targets
  3003. Xof this recipe, it is simply supplementary to any other recipe,
  3004. Xusually an implicit recipe.
  3005. X.P
  3006. XThe expressions are only evaluated into words when the recipe is instanciated.
  3007. X.H 3 "Commands"
  3008. XCommands may take several forms in
  3009. X.BR cook .
  3010. XThey all have one thing in common; they execute a command.
  3011. X.eB
  3012. Xstatement
  3013. X    = command
  3014. X    .
  3015. X.eE
  3016. X.H 4 "The Simple Command Statement"
  3017. XThe simplest command form is
  3018. X.eB
  3019. Xcommand
  3020. X    = simple_command
  3021. X    .
  3022. Xsimple_command
  3023. X    = elist flags '\fB;\fP'
  3024. X    .
  3025. X.eE
  3026. XWhen executed,
  3027. Xthe
  3028. X.I elist
  3029. Xis evaluated into a word list
  3030. Xand used as a command to be passed to the operating system.
  3031. XWhile this is usually sufficient,
  3032. Xsome programs, 
  3033. Xnotably
  3034. X.IR newgrp (1),
  3035. Xrequire slightly more.
  3036. X.H 4 "The Data Command Statement"
  3037. XFor programs which require
  3038. X.I stdin
  3039. Xto be supplied by 
  3040. X.B cook
  3041. Xto perform their functions,
  3042. Xthe data command statement has been provided.
  3043. X.eB
  3044. Xcommand
  3045. X    = simple_command
  3046. X    '\fBdata\fP'
  3047. X        expr
  3048. X    '\fBdataend\fP'
  3049. X    .
  3050. X.eE
  3051. XIn this form,
  3052. Xthe 
  3053. X.I expr
  3054. Xis evaluated and used as input to the
  3055. Xcommand.
  3056. XBetween the
  3057. X.B data
  3058. Xand 
  3059. X.B dataend
  3060. Xkeywords the definition of the special symbols and whitespace change.
  3061. XThere are only two special symbols,
  3062. X.B [
  3063. Xand
  3064. X.BR ] ,
  3065. Xto allow functions and variable references to appear in the expression.
  3066. XIn addition,
  3067. Xwhitespace ceases to have its usual specialness;
  3068. Xit is handed to the command,
  3069. Xinstead.
  3070. X.P
  3071. XThe
  3072. X.B data
  3073. Xkeyword must be the last on a line,
  3074. Xwhitespace after the 
  3075. X.B data
  3076. Xkeyword up to and including end-of-line,
  3077. Xwill 
  3078. X.I not
  3079. Xbe given to the command.
  3080. X.P
  3081. XThe 
  3082. X.B dataend
  3083. Xkeyword must appear alone on a line,
  3084. Xoptionally surrounded by whitespace;
  3085. Xit is is not alone,
  3086. Xit is not a 
  3087. X.B dataend
  3088. Xkeyword and will not terminate the expression.
  3089. X.P
  3090. XAn example of this may be useful.
  3091. X.eB
  3092. X/usr/fred/%: %
  3093. X    {
  3094. X        newgrp fred;
  3095. X            data
  3096. X                cp % /usr/fred/%
  3097. X            dataend
  3098. X    }
  3099. X.eE
  3100. XIf the directory
  3101. X.I /usr/fred
  3102. Xhas read-only permissions for others,
  3103. Xand group write permissions,
  3104. Xand belonged to group
  3105. X.IR fred ,
  3106. Xand you were a member of group
  3107. X.IR fred ,
  3108. Xthe above implicit recipe could be used to copy the file.
  3109. X.H 4 "The Fail Statement"
  3110. X.B Cook
  3111. Xcan be forced to think that a recipe has failed
  3112. Xby the uses of the 
  3113. X.B fail
  3114. Xstatement.
  3115. X.eB
  3116. Xstatement
  3117. X    = '\fBfail\fP' '\fB;\fP'
  3118. X    .
  3119. X.eE
  3120. XThis is hugely useful when programs do not return a useful exit
  3121. Xstatus,
  3122. Xbut 
  3123. X.I do
  3124. Xfail to produce the goods.
  3125. X.P
  3126. XAnother variation of this statement is
  3127. X.eB
  3128. Xstatement
  3129. X    = '\fBfail\fP' '\fBbacktrack\fP' '\fB;\fP'
  3130. X    .
  3131. X.eE
  3132. XThis enables you to write a recipe which will succeed if all of the ingredients are up-to-date,
  3133. Xbut cause 
  3134. X.B cook
  3135. Xto backtrack if any of the ingredients are out-of-date.
  3136. XIt is useful with some software configuration management systems.
  3137. X.H 3 "Flow Control"
  3138. XThis section details statement forms which the casual user will never need.
  3139. X.H 4 "The If Statement"
  3140. XThe if statement has one of two forms.
  3141. X.eB
  3142. Xstatement
  3143. X    = '\fBif\fP' expr '\fBthen\fP' statement
  3144. X    | '\fBif\fP' expr '\fBthen\fP' statement '\fBelse\fP' statement
  3145. X    .
  3146. X.eE
  3147. XIn nested if statements,
  3148. Xthe
  3149. X.B else
  3150. Xwill bind to the closest
  3151. X.BR else -less
  3152. X.BR if .
  3153. X.P
  3154. XAn expression is false if and only if all of its words are null or it
  3155. Xhas no words.
  3156. X.H 4 "The Loop and Loopend Statements"
  3157. XLooping is provided for in 
  3158. X.B cook
  3159. Xby the generic infinite loop construct defined below.
  3160. XA facility is provided to break out of a loop at any point.
  3161. X.eB
  3162. Xstatement
  3163. X    = '\fBloop\fP' statement
  3164. X    | '\fBloopstop\fP' '\fB;\fP'
  3165. X    .
  3166. X.eE
  3167. XThe statement following the 
  3168. X.B loop
  3169. Xdirective is executed repeatedly forever.
  3170. XThe
  3171. X.B loopstop
  3172. Xstatement is only semantically valid within the scope of a 
  3173. X.B loop
  3174. Xstatement.
  3175. END_OF_FILE
  3176. if test 18062 -ne `wc -c <'doc/language'`; then
  3177.     echo shar: \"'doc/language'\" unpacked with wrong size!
  3178. fi
  3179. # end of 'doc/language'
  3180. fi
  3181. echo shar: End of archive 8 \(of 11\).
  3182. cp /dev/null ark8isdone
  3183. MISSING=""
  3184. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  3185.     if test ! -f ark${I}isdone ; then
  3186.     MISSING="${MISSING} ${I}"
  3187.     fi
  3188. done
  3189. if test "${MISSING}" = "" ; then
  3190.     echo You have unpacked all 11 archives.
  3191.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  3192. else
  3193.     echo You still need to unpack the following archives:
  3194.     echo "        " ${MISSING}
  3195. fi
  3196. ##  End of shell archive.
  3197. exit 0
  3198.